自動化的 Web 集成測試對於保證軟體質量是很有效的,但是編寫和維護這些測試用例卻不是一件容易的事。本文介紹的是一種利用 Ruby 實現業務驅動的集成測試方法, 通過該方法,讀者能夠脫離複雜的技術細節,把注意力集中到業務邏輯的測試中來。
簡介
對 Web 應用程序來講,自動化的集成測試是一個非常重要的部分, 然而由於這些測試用例太依賴具體的 Web 頁面的實現細節,這就給編寫和維護帶來的很大的挑戰。 通常來講有兩種方法可以生成 Web 應用程序測試用例。
方法 1 需要測試人員了解太多的 Web 頁面細節,這就使得測試人員不能把精力集中在業務邏輯上,一旦 Web 頁面發生變化,將不得不花費大量精力更新腳本。方法 2 能夠自動生成測試腳本,但是這些腳本的可讀性很差,導致很難維護。同樣如果 Web 頁面發生變化,測試人員也需要重新錄製所有的腳本。
那麼有沒有辦法克服上述問題,讓工作更加輕鬆一點呢?答案是肯定的!
例如一個在線的電子書店,對於用戶購書的場景,我們可以用下面的腳本來進行集成測試 :
login 'test@test.com','pass4you' // 登錄 list_books // 列出書籍 add_to_shop_cart '誰說大象不能跳舞' // 把《誰說大象不能跳舞》這本書加入到購物車中 |
讀者可以看到, "login" , "list_books", "add_to_shop_cart" 這些術語已經完全脫離了具體的頁面細節,將不會受到頁面變化的影響, 它們是完全面向業務的,準確的體現了應用的業務邏輯,容易理解、易於維護,並且還能拿來和業務人員進行交流,甚至業務人員自己都能編寫測試腳本。 有這麼多的優點,那麼如何實現它們呢?這正是本文要介紹的重點:利用動態語言 Ruby 來實現“業務驅動”的 Web 應用測試。
Ruby 介紹
Ruby,中文意思為紅寶石,但是在計算機領域,它代表一種相當優秀的面向對象的腳本程序語言。它誕生於 1993 年,近年來隨著 Ruby on Rails 這個“Killer application”在 Web 開發領域迅速躥紅。Ruby 在最初設計時吸收了很多別的語言的精華,例如 perl 語言的文本處理能力,Python 語言的簡單性和可讀性,以及方便的擴展能力和強大的可移植能力,Smalltalk 語言的純面向對象語法思想,這就使它具備了很多其他語言的優點。Ruby 的設計理念是盡量減少編程時不必要的瑣碎工作,讓程序員在完成任務的同時充分的享受編程的樂趣。
Ruby 的特點如下:
例如在 Java 中,對一個數求絕對值用 Math.abs(-20)
, 但在 Ruby 中一切皆對象,-20 這個數也是對象,所以可以這麼做 -20.abs
, 是不是更加形象和直觀?
本文的重點不是介紹 Ruby 語言本身,有興趣的讀者可以參見 參考資源 部分。
案例分析
51book
為了展示如何使用 Ruby 進行業務驅動的測試,同時又不讓讀者陷入到過多細節中,本文假想了一個簡單的在線購書應用 ( 簡稱 51book),這個應用支持如下主要功能:
業務操作
通過上面的介紹,讀者應該對 51book 有了一個簡單的了解,接下來我們考慮如何進行業務驅動的測試,首先需要定義面向業務的操作,這樣才能在測試用例中使用它們。 簡單起見,我們定義如下業務操作:
業務操作 | 功能說明 |
---|---|
login "user_name", "password" | 該操作接受用戶名和密碼,觸發在 Web 界面的登錄 |
add_to_shop_cart "book_title" | 該操作接受一個書籍名稱為參數,可以把當前頁面的該書籍加入到購物車中 |
search_book "book_title" | 該操作以書籍名稱為參數來搜索書籍 |
change_quantity "book_title" | 該操作改變一本書在購物車中的數量 |
recalculate_cart "book_title" | 該操作在改變了購物車中的內容后,可以重新計算總價格 |
assert_total_price_is "price" | 該操作實際上是個斷言 (Assert), 它被用來 Assert 購物車中的總價格和測試人員的期待是相符的 |
領域專用語言 (Domain Specific Language)
所謂領域專用語言(domain specific language / DSL),其基本思想是“求專不求全”,不像通用目的語言那樣目標範圍涵蓋一切軟體問題, 而是專門針對某一特定問題的計算機語言。正如它的名稱所宣稱的那樣,這種語言並不是通用的,只是專註於某個特定的“領域”, 例如 SQL 語言就是資料庫的 DSL,使用 SQL 可以完成各種各樣數據的操作,而不用關心底層的具體資料庫實現。由於“領域專用”,你想用 SQL 來開發一個桌面應用程序是不可能的。
我們在上一節定義的 login
, add_to_shop_cart
, change_quantity
就是針對 51book 在線書店的 DSL。
Martin Fowler 把 DSL 分為兩大類:外部 DSL 和內部 DSL。對外部 DSL 來講,構建它需要做的是:(1) 定義面向領域的全新的語法。(2) 用某種語言編寫解釋器或編譯器 ,由於這種語言是全新的,我們有很多工作需要做;那麼對於內部 DSL 來說,我們可以選定一種靈活的語言,選取它一個語法的子集,並且利用這種語言的動態特性進行定製,這樣就避免了重新打造一個全新語言的龐大工作量。
Ruby 語言具備非常豐富的語法和異常靈活的動態特徵,非常適合創建動態 DSL。本文就是利用 Ruby 來創建 51book 面向測試的 DSL。
用 Ruby DSL 實現業務操作
原理
由於 Ruby 是一種動態腳本語言,是解釋執行的,它提供了對一段文本進行 “evaluate
”執行的方法。也就是說,我們可以提供一段文本(不必是完整的程序),Ruby 就可以在一個特定的上下文中執行它,當然這段文本需要符合 Ruby 的語法。
比如我們有一個文件 bookshop.txt,它包含了如下文本 : login "andy", "pass4you" , 那麼怎麼執行它呢?首先需要一個上下文,我們可以定義一個類來表示:
class BookshopDSLBuilder def self.execute( dsl) builder=new builder.instance_eval(File.read(dsl), dsl) end def login(user=nil,pwd=nil) print user print pwd end end |
上面的代碼非常簡單,需要關注的是靜態方法
[火星人 ] 使用 Ruby 實現業務驅動的 Web 應用程序測試已經有507次圍觀