1. 程式人生 > >用Selenium測試web應用

用Selenium測試web應用

問題1:當用戶在網上商店購物時,一次完整的購買流程需要使用者進行好幾個步驟的操作(包括選擇商品、填寫訂單資訊、選擇支付方式、確認訂單等),涉及四到五個頁面以及數十個類的協作。如何在開發過程中始終確保該流程能夠正確無誤、暢通無礙?

問題2:客戶提出需求:在顯示貨物列表時,應該首先按貨物名稱排序,名稱相同的貨物再按照價格排序。我們已經實現了這一功能,並且有單元測試作為保障,但如何讓客戶看到我們的成果?

問題3:美工在製作頁面時,一不小心把一個<form>id屬性刪掉了。幾天之後,另一個頁面上的JavaScript莫名其妙地失效,我們花了很多時間才發現這個問題。應該如何避免類似的情況再次發生?

這三個問題對於做慣了web應用的讀者來說一定不陌生——實際上,我們的每個專案都或多或少地遇到類似的問題。說穿了,這三個問題都是關於同一件事情:如何驗證一個東西是正確的,以及如何便利而自動地重複這一驗證過程。在程式碼層面上,xUnit單元測試工具(對於J2EE專案,就是Junit)給了我們幫助。但是,當問題涉及到web介面和使用者互動時,JUnit就顯得有些力不從心了,這也是很多采用測試驅動開發(TDD)方法的團隊只能把TDD貫徹到web controller層面的原因。

單元測試 vs. 功能測試

正如它的名字所揭示的,JUnit是一個單元測試工具。而我們在前面提出的三個問題,實際上已經屬於功能測試(

functional test)或者驗收測試(acceptance test)的範疇。儘管單元測試能夠保證各個單元的正確,卻無法確保將這些單元組合起來之後的效果。需要依靠功能測試工具,我們才能繼續TDD的腳步。

另一方面,功能測試在很多時候應該由客戶——或者是具有一定技術背景的客戶代表(可能是專案的需求分析師)——來編寫的(這也是“驗收測試”這個名稱的由來:通過這些測試就代表工作通過驗收),因此編寫這些測試不應該要求太高的程式設計能力。在這一點上,JUnit也是令人望而生畏的。

ThoughtWorks員工開發並維護的Selenium

http://selenium.thoughtworks.com)正是幫助我們解決上述問題的得力工具。簡單地說,Selenium是一個自動化的web應用功能測試工具——我知道,這個短語不足以讓讀者瞭解它所描述的物件。所以,在進一步介紹之前,我想先請讀者來看一個活生生的例子。請開啟你的瀏覽器,訪問下列URL地址:

你將會看到Selenium的主操作介面(如圖1)。可以看到,整個頁面被分成四個部分。左上角的“Test Suite”區域顯示出當前執行的測試套件包含哪些測試用例;中間上部的“Current Test”區域顯示出當前執行的測試用例;右上角的“Control Panel”區域是給使用者操作的區域。至於下面的一大片空間,它會在執行測試的過程中起到重要的作用,我們稍後就會看到。

1Selenium主介面

點選“Control Panel”區域中的“All”按鈕,讀者會——或許有點驚訝地——發現,螢幕上的文字和顏色開始飛快地發生變化。如果你還沒有明白這是怎麼回事,可以先把按鈕上方的單選按鈕放在“walk”上,然後再點選按鈕。這時你會清楚地看到,原來Selenium正在逐個執行套件中的測試用例:執行測試用例中指定的操作,並進行指定的條件判斷。至於螢幕下方的大塊空白區域,此刻正在模擬著實際的使用者操作。而那些淡綠色的橫條,熟悉JUnit的你應該不難猜到,正是測試通過的象徵——看到這些綠色橫條讓你感到心情愉悅,不是嗎?

2:測試套件執行完畢

讀者可以看到,“Control Panel”區域中還顯示著本次測試的相關資訊:耗時10秒,執行3個測試用例,共有10個判斷條件,所有測試都通過,沒有失敗或未完成的測試。此外,如果點選一個測試用例,再點選“Selected”按鈕,就可以單獨執行這一個測試用例;如果選中“Step”選項,就可以進行單步跟蹤執行。這些功能,相信聰明的讀者只需要稍微嘗試一下就會全部掌握了。

經過幾分鐘的探索,讀者應該能夠明白這個Demo的奧妙所在了。沒錯,Selenium採用JavaScript來管理整個測試過程,包括讀入測試套件、執行測試和記錄測試結果——這在很大程度上得益於強大的JavaScript單元測試工具JSUnithttp://www.edwardh.com/jsunit/),正是有它的幫助,Selenium才能夠模擬真實的使用者操作,包括瀏覽頁面、點選連結、輸入文字、提交表單等等,並且能夠對結果頁面進行種種驗證。也就是說,只要在測試用例中把預期的使用者行為與結果都描述出來,我們就得到了一個可以自動執行的功能測試套件。而且,我們習慣的測試驅動開發方法也可以延伸到web表現層:我們可以先寫測試、執行測試並看到它失敗、然後編寫功能程式碼讓測試通過。

現在,如果你已經對Selenium產生了興趣,我將帶領你開始真正的Selenium測試之旅。首先,請到以下地址下載最新版本的Selenium(當然,作為一個J2EE開發者,我假設你已經安裝了JDKservlet容器譬如Tomcat):

Selenium的故事

在等待下載的過程中,不妨先聽我講講和Selenium有關的故事。正如我在前面提到過的,SeleniumThoughtWorks員工在業餘時間開發並維護的開源專案,並且在ThoughtWorks的專案中被廣泛應用。不過,真正有趣的是它名字的來歷:在Selenium出現之前,最著名的web應用功能測試工具當屬Mercury Quanlity Centerhttp://www.mercury.com/us/products/quality-center/),但那是一個商業工具,功能強大卻也價格不菲,常常讓開發者們又愛又恨。所以,自己動手開發開源功能測試工具的ThoughtWorker們把這個工具叫做Selenium——“mercury”有“水銀”的意思,而“selenium”(硒元素)恰好是專解汞中毒的特效藥。

把下載的壓縮包解壓之後,你會得到兩個目錄:docselenium。只要把後者複製到你的web伺服器根目錄(對於Tomcat,就是webapps目錄)下,就算是完成Selenium的安裝了。安裝好之後,可以啟動web伺服器,然後試著訪問下列URL地址(假設你也像我一樣,把Tomcat開在8080埠上):

在這裡,你應該又會看到那個熟悉的主操作介面(如圖3)。不妨試著執行一下這些測試,看看它們是否能夠在你本地的機器上正常執行。確認一切正常之後,我們再來編寫自己的測試。

3:在本地執行Selenium

預設情況下,Selenium會從tests目錄下的TestSuite.html檔案載入測試套件,但我們也可以指定從別的檔案載入。首先,我們在tests目錄下建立一個MyTestSuite.html檔案,然後在其中定義我們的測試套件:

<html>

<head>

<title>My First Test Suite</title>

</head>

<body>

<table cellpadding="1" cellspacing="1" border="1">

<tbody>

<tr><td><b>Test Suite</b></td></tr>

<tr><td>

<a href="./MyTests/TestHello.html">Test Say Hello</a>

</td></tr>

</tbody>

</table>

</body>

</html>

然後,在tests/MyTests目錄下建立TestHello.html檔案,在其中描述我們要做的動作和期望得到的結果:

<html>

<head>

<title>Test Hello</title>

</head>

<body>

<table cellpadding="1" cellspacing="1" border="1">

<tbody>

<tr>

<td rowspan="1" colspan="3">Test Say Hello To World<br>

</td>

</tr>

<tr>

<td>open</td>

<td>/sample/hello.jsp</td>

<td>&nbsp;</td>

</tr>

<tr>

<td>verifyTextPresent</td>

<td>Hello, World!</td>

<td>&nbsp;</td>

</tr>

</tbody>

</table>

</body>

</html>

測試套件和測試用例的寫法都是一目瞭然的。在測試用例中,我們首先訪問/sample/hello.jsp這個地址(open命令),然後驗證頁面上有“Hello, World!”字樣存在(verifyTextPresent命令)。在Seleniumdoc目錄下,你可以找到完整的命令幫助列表。現在訪問http://localhost:8080/selenium/TestRunner.html?test=tests/MyTestSuite.html這個地址,應該就可以看到我們的測試套件,當然現在執行它會看到紅色的失敗資訊。

4:執行我們的第一個測試,失敗了

熟悉TDD過程的讀者現在不僅不會失望,反而會感到興奮,因為這個失敗的測試為我們指出了目標。為了讓測試通過,我們可以建立一個名為sampleweb應用,在其中放上hello.jsp這個檔案,讓它向世界問好。然後,我們就可以享受成功的喜悅了。

5:我們的第一個Selenium測試通過了

繼續這個過程:編寫測試--編寫功能程式碼-綠……隨著我們一步步前進,測試用例也會逐漸增加,最終構成一張龐大而嚴密的安全網。不僅是Java程式,在Selenium的幫助之下,介面的開發工作同樣可以用TDD的方式來進行。而且,由於是架設在JavaScript的基礎上,Selenium並不僅限於J2EE web應用的測試,實際上各種web應用都有它的用武之地。

作為一篇簡介,本文只能幫助讀者對Selenium建立一個最基本的瞭解,更多的知識與技巧還有待讀者去探索。譬如說,在持續整合的環境下,可以用Ant來驅動Selenium測試,並將測試結果彙報給CruiseControl,從而實現更加嚴格的整合管理。在下次的文章中,我將向讀者介紹ThoughtWorks公司採用測試驅動開發的一些技巧與實踐(當然也包括Selenium的使用心得)。現在,讓我們先說再見吧,希望你程式設計愉快。