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