自動(dòng)測(cè)試可以節(jié)省重復(fù)執(zhí)行相同測(cè)試步驟的
時(shí)間和精力。本文將介紹 jWebUnit,這是一組 Java 類,用于為 Web 應(yīng)用程序開(kāi)發(fā)測(cè)試用例。jWebUnit 是一個(gè)開(kāi)源項(xiàng)目,可以在
BSD 許可下免費(fèi)獲得。我將介紹如何下載 jWebUnit 庫(kù)、配置 Eclipse 平臺(tái)來(lái)開(kāi)發(fā) jWebUnit
測(cè)試用例,以及如何構(gòu)建一個(gè)示例測(cè)試用例。
jWebUnit 簡(jiǎn)介
jWebUnit 以 HttpUnit(一個(gè)進(jìn)行 Web 應(yīng)用程序自動(dòng)測(cè)試的 Java 庫(kù))和 JUnit 單元測(cè)試框架為基礎(chǔ)(請(qǐng)參閱 參考資料)。
jWebUnit 提供了導(dǎo)航 Web 應(yīng)用程序的高級(jí)
API,并組合了一組斷言,用它們來(lái)驗(yàn)證鏈接導(dǎo)航、表單輸入項(xiàng)和提交、表格內(nèi)容以及其他典型商務(wù) Web 應(yīng)用程序特性的正確性。 jWebUnit 以
JAR 文件形式提供的,可以很容易地將它插入大多數(shù) IDE 中,jWebUnit 也包含其他必要的庫(kù)。
用 HttpUnit 進(jìn)行測(cè)試
對(duì)
Web 應(yīng)用程序自動(dòng)進(jìn)行測(cè)試意味著跳過(guò) Web 瀏覽器,通過(guò)程序來(lái)處理 Web 站點(diǎn)。首先,我要介紹 HttpUnit(JWebUnit
的構(gòu)建塊之一)是如何簡(jiǎn)化這項(xiàng)工作的。HttpUnit 可以模擬幀、JavaScript、頁(yè)面重定向 cookie,等等。在將 HttpUnit
用于 JUnit 時(shí),它可以迅速地對(duì) Web 站點(diǎn)的功能進(jìn)行驗(yàn)證。
清單 1 顯示了一個(gè)用 HttpUnit 編寫(xiě)的測(cè)試用例,它試圖單擊 HttpUnit 主頁(yè)上的“Cookbook”鏈接:
清單 1. 單擊 HttpUnit 主頁(yè)上 Cookbook 鏈接的 HttpUnit 代碼
1 public class HttpUnitTest {
2 public static void main(String[] args) {
3 try {
4 WebConversation wc = new WebConversation();
5 WebRequest request =
new GetMethodWebRequest("http://httpunit.sourceforge.net/index.html");
6 wc.setProxyServer( "your.proxy.com", 80 );
7 WebResponse response = wc.getResponse(request);
8 WebLink httpunitLink =
response.getFirstMatchingLink(WebLink.MATCH_CONTAINED_TEXT,"Cookbook");
9 response = httpunitLink.click();
10 System.out.println("Test successful !!");
11 } catch (Exception e) {
12 System.err.println("Exception: " + e);
13 }
14 }
15 }
|
清單 1 中的代碼用 your.proxy.com
(第 6 行)連接 Internet。如果存在直接 Internet 連接,那么可以把這個(gè)語(yǔ)句注釋掉。第 8 行的語(yǔ)句在頁(yè)面中搜索包含文本 Cookbook 的 Web 鏈接。第 9 行的語(yǔ)句用于單擊這個(gè)鏈接。如果找到鏈接,那么用戶會(huì)看到 Test Successful !!
這條消息。
用 jWebUnit 進(jìn)行的測(cè)試更簡(jiǎn)單
清單 2 的測(cè)試用例用 jWebUnit API 執(zhí)行和清單 1 相同的任務(wù):
清單 2. 單擊 HttpUnit 主頁(yè)上 Cookbook 鏈接的 jWebUnit 代碼
1 public class JWebUnitTest extends WebTestCase{
2 public static void main(String[] args){
3 junit.textui.TestRunner.run(new TestSuite(JWebUnitTest.class));
4 }
5 public void setUp(){
6 getTestContext().setBaseUrl("http://httpunit.sourceforge.net");
7 getTestContext().setProxyName("webproxy.watson.ibm.com");
8 getTestContext().setProxyPort(8080);
9 }
10 public void testSearch(){
11 beginAt("/index.html");
12 clickLinkWithText("Cookbook");
13 }
14 }
|
如果沒(méi)注意清單 2 中特定于 JUnit 的代碼,那么您可以看到,測(cè)試用例現(xiàn)在變得相當(dāng)整潔、簡(jiǎn)練。需要查看的重要的行是第 6 行、第 11 行和第 12 行。在第 6 行,基本 URL 被設(shè)置到 HttpUnit 的主頁(yè)中。第 11 行用相對(duì)路徑 /index.html
連接站點(diǎn)。第 12 行用于單擊頁(yè)面上具有文本 Cookbook 的鏈接。如果鏈接有效,那么 JUnit 會(huì)報(bào)告成功;否則,JUnit 會(huì)報(bào)告異常。
jWebUnit API:進(jìn)一步觀察
每個(gè) jWebUnit 測(cè)試的核心都是 net.sourceforge.jwebunit.WebTestCase
類,它代表測(cè)試用例。每個(gè)測(cè)試用例都必須是從這個(gè)類擴(kuò)展而來(lái)。(net.sourceforge.jwebunit.WebTestCase
類本身則是從 junit.framework.TestCase
類擴(kuò)展而來(lái)的,它在 JUnit 中代表測(cè)試用例。) 表 1 描述了這個(gè)類的一些常用方法:
表 1. net.sourceforge.jwebunit.WebTestCase 類的重要方法
方法 |
說(shuō)明 |
public TestContext getTestContext() |
得到測(cè)試用例的上下文。可以用它訪問(wèn)像地區(qū)、基本 URL 和 cookie 之類的項(xiàng)目 |
public void beginAt(String relativeURL) |
在相對(duì)于基本 URL 的 URL 處開(kāi)始對(duì)話 |
public void setWorkingForm(String nameOrId) |
與指定的表單開(kāi)始交互。如果當(dāng)前頁(yè)面只有一個(gè)表單,就不需要調(diào)用這個(gè)方法 |
protected void submit() |
提交表單 —— 等同于單擊表單的 提交 按鈕 |
public void gotoFrame(String frameName) |
激活命名幀 |
另一個(gè)重要的類是 net.sourceforge.jwebunit.TestContext
。它為測(cè)試創(chuàng)建上下文。可以用這個(gè)類來(lái)處理像 cookie、會(huì)話和授權(quán)之類的信息。表 2 顯示了這個(gè)類的一些重要方法:
表 2. net.sourceforge.jwebunit.TestContext 類的重要方法
方法 |
說(shuō)明 |
public void addCookie(String name, String value) |
向測(cè)試上下文中添加 cookie。在 HttpUnitDialog 開(kāi)始時(shí),添加的 cookie 被設(shè)置到 WebConversation 上 |
public void setResourceBundleName(String name) |
為測(cè)試上下文設(shè)置一個(gè)使用的資源綁定。用于按照 WebTester 中的鍵查找期望的值 |
public void setProxyName(String proxyName) |
為測(cè)試上下文設(shè)置代理服務(wù)器名稱 |
public void setBaseUrl(String url) |
為測(cè)試上下文設(shè)置基本 URL |
下載 jWebUnit,在 Eclipse 中配置 jWebUnit
jWebUnit 是用純 Java 代碼實(shí)現(xiàn)的,所以可以以 JAR 文件的形式獲得它 (請(qǐng)參閱 參考資料,從中獲得下載鏈接)。在完成下載之后,請(qǐng)按以下步驟在 Eclipse 平臺(tái)上配置 jWebUnit 庫(kù):
- 把下載的文件 jwebunit-1.2.zip 釋放到臨時(shí)目錄中(假設(shè)是 C:\temp)。
- 在 Eclipse 中創(chuàng)建新 Java 項(xiàng)目,將其命名為 jWebUnit。
- 右擊 Package Explorer 視圖中的 jWebUnit 項(xiàng)目,然后選擇 Properties。
- 單擊 Java Build Path。單擊 Libraries 標(biāo)簽中的 Add External JARs。
- 瀏覽到 C:\temp\jwebunit-1.2\lib 目錄,選擇這個(gè)目錄中的所有 JAR 文件。
- 單擊 OK。
現(xiàn)在可以在 Eclipse 中的 jWebUnit 項(xiàng)目下開(kāi)發(fā) jWebUnit 測(cè)試用例了。
構(gòu)建示例應(yīng)用程序
現(xiàn)在就可以查看 jWebUnit API 的實(shí)際應(yīng)用了。我將帶您研究一個(gè)示例應(yīng)用程序,幫助您更好地理解 jWebUnit 的真正威力。這個(gè)應(yīng)用程序是一個(gè)測(cè)試用例,用于打開(kāi)一個(gè) Google 搜索頁(yè)面并搜索文本 HttpUnit。應(yīng)用程序需要測(cè)試以下場(chǎng)景:
- 打開(kāi) Google 主頁(yè) http://www.google.com。
- 確定該頁(yè)包含一個(gè)名為
q
的表單元素。(在 Google 的主頁(yè)上,名為 q
的文本框是接受用戶查詢輸入的文本框。)應(yīng)用程序用這個(gè)元素輸入搜索參數(shù)。
- 在搜索文本框中輸入字符串
HttpUnit Home
,并提交表單。
- 獲得結(jié)果頁(yè),并確定該頁(yè)面包含的鏈接中包含文本 HttpUnit Home。
- 單擊包含文本 HttpUnit Home 的鏈接。
現(xiàn)在測(cè)試場(chǎng)景已經(jīng)就緒,可以編寫(xiě) Java 應(yīng)用程序,用 jWebUnit 實(shí)現(xiàn)這些需求了。
第一步是聲明一個(gè)從 WebTestCase
擴(kuò)展而來(lái)的類,如清單 3 所示:
清單 3. 聲明測(cè)試用例類
public class GoogleTest extends WebTestCase {
static String searchLink = "";
}
|
正如我在前面提到過(guò)的,jWebUnit 要求每個(gè)測(cè)試用例都是從 WebTestCase
中擴(kuò)展而來(lái)的。searchLink
保存?zhèn)魅氲乃阉鲄?shù)。這個(gè)值以命令行參數(shù)的形式傳遞給測(cè)試用例。
下一步是聲明入口點(diǎn) —— main()
方法,如清單 4 所示:
清單 4. main()
方法
public static void main(String[] args) {
searchLink = args[0];
junit.textui.TestRunner.run(new TestSuite(GoogleTest.class));
}
|
main()
方法調(diào)用 junit.textui.TestRunner.run()
執(zhí)行 JTest
測(cè)試用例。因?yàn)樾枰\(yùn)行 GoogleTest
測(cè)試用例,所以,作為參數(shù)傳遞給 run()
方法的測(cè)試套件采用 GoogleTest.class
作為參數(shù)。
接下來(lái),JTest
調(diào)用 setUp()
方法來(lái)設(shè)置基本 URL 和代理,如清單 5 所示:
清單 5. 設(shè)置
public void setUp() {
getTestContext().setBaseUrl("http://www.google.com");
getTestContext().setProxyName("proxy.host.com");
getTestContext().setProxyPort(80);
}
|
清單 5 把基本 URL 設(shè)置為 http://www.google.com
。這意味著測(cè)試用例的啟動(dòng)是相對(duì)于這個(gè) URL 的。下面兩個(gè)語(yǔ)句設(shè)置連接到 Internet 的代理主機(jī)和代理端口。如果是直接連接到 Internet,那么可以忽略代理設(shè)置語(yǔ)句。
現(xiàn)在開(kāi)始瀏覽站點(diǎn)并輸入搜索參數(shù)。清單 6 顯示了訪問(wèn) Web 頁(yè)面,然后測(cè)試所有場(chǎng)景的代碼:
清單 6. 測(cè)試所有場(chǎng)景
public void testSearch() {
beginAt("/");
assertFormElementPresent("q");
setFormElement("q", "HttpUnit");
submit("btnG");
assertLinkPresentWithText(searchLink);
clickLinkWithText(searchLink);
}
|
清單 6 的代碼連接到基本 URL,并相對(duì)于 /
開(kāi)始瀏覽。然后它斷定頁(yè)面中包含一個(gè)名為 q
的表單元素 —— q 是 Google 主頁(yè)上查詢輸入文本框的名稱。下一條語(yǔ)句用值 HttpUnit
設(shè)置名為 q
的文本框。再下一條語(yǔ)言提交表單上名為 btnG
的提交按鈕。(在 Google 的主頁(yè)上,名為 btnG
的按鈕是標(biāo)簽為 Google Search 的按鈕。)表單是在這個(gè)對(duì)話中提交的,下一頁(yè)列出搜索結(jié)果。在結(jié)果頁(yè)面上,代碼首先檢查是否有一個(gè)鏈接的文本是 HttpUnit Home。如果該鏈接不存在,那么測(cè)試就以 AssertionFailedError
失敗。如果該鏈接存在,則測(cè)試執(zhí)行的下一個(gè)操作是單擊鏈接。
運(yùn)行示例應(yīng)用程序
現(xiàn)在把示例應(yīng)用程序投入使用當(dāng)中:
- 下載示例應(yīng)用程序 j-webunitsample.jar (請(qǐng)參閱 下載)。
- 在一個(gè)目錄中解壓縮 j-webunitsample.jar。例如,如果把它釋放到 C:\temp 中,那么就要把源文件和類文件放在 C:\temp\com\jweb\test 中,而 setclasspth.bat 則放在 C:\temp 中。
- 編輯 setclasspath.bat:設(shè)置
JAR_BASE
指向包含所有必需 JAR 文件的目錄。例如,如果在 C:\temp 中釋放 jwebunit-1.2.zip 文件,那么將 JAR_BASE 設(shè)置為 C:\temp\jwebunit-1.2\lib。
- 打開(kāi)命令行提示符,切換到 C:\temp 目錄。
- 執(zhí)行
setclasspath.bat
。這會(huì)設(shè)置執(zhí)行測(cè)試用例所需的 CLASSPATH
。
- 用命令
java com.jweb.test.GoogleTest "HttpUnit Home"
運(yùn)行應(yīng)用程序。
示例輸出
在執(zhí)行了測(cè)試用例之后,會(huì)在命令行輸出一個(gè)測(cè)試用例報(bào)告。如果測(cè)試失敗,報(bào)告看起來(lái)如清單 7 中所示:
清單 7. 帶有斷言失敗的輸出
C:\temp>java com.jweb.test.GoogleTest "HttpUnit Hwee"
.F
Time: 5.338
There was 1 failure:
1) testSearch(com.jweb.test.GoogleTest)junit.framework.AssertionFailedError: Link
with text [HttpUnit Hwee] not found in response.
at net.sourceforge.jwebunit.WebTester.assertLinkPresentWithText(WebTester.java:618)
at net.sourceforge.jwebunit.WebTestCase.assertLinkPresentWithText(WebTestCase.java:244)
at com.jweb.test.GoogleTest.testSearch(GoogleTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at com.jweb.test.GoogleTest.main(GoogleTest.java:19)
FAILURES!!!
Tests run: 1, Failures: 1, Errors: 0
|
正如在清單 7 中可以看到的,可以用 HttpUnit Hwee
作為參數(shù)來(lái)執(zhí)行測(cè)試用例。這個(gè)測(cè)試用例遇到斷言的地方會(huì)失敗,因?yàn)榻Y(jié)果頁(yè)面中不包含帶有這個(gè)文本的鏈接。由此也就產(chǎn)生了junit.framework.AssertionFailedError
。
清單 8 執(zhí)行時(shí)用 HttpUnit Home
作為參數(shù)。測(cè)試用例找到一個(gè)帶有這個(gè)文本的鏈接,所以測(cè)試通過(guò)了:
清單 8. 成功測(cè)試的輸出
C:\temp>java com.jweb.test.GoogleTest "HttpUnit Home"
.
Time: 6.991
OK (1 test)
|
結(jié)束語(yǔ)
本
文通過(guò)討論 jWebUnit 框架的一些突出特性和最重要的類,介紹如何用它創(chuàng)建簡(jiǎn)潔的測(cè)試用例,讓您對(duì) jWebUnit
框架有一個(gè)認(rèn)識(shí)。jWebUnit 還有更多特性可以用在測(cè)試用例中。它支持測(cè)試 Web
頁(yè)面中的鏈接行數(shù)。可以對(duì)字符串、表或者帶有指定標(biāo)簽的表單輸入元素是否存在于頁(yè)面上進(jìn)行斷言。此外,jWebUnit 還可以處理 cookie
(例如斷言存在某個(gè) cookie、刪除 cookie 等。)測(cè)試可以對(duì)某個(gè)文本之后出現(xiàn)的特定文本的鏈接進(jìn)行單擊。 如果想為 Web
應(yīng)用程序構(gòu)建快而有效的測(cè)試用例,jWebUnit 可能是您最好的朋友。