HttpUnit是一個整合測試載入器,主要關注Web應用的測試,提供的協助類讓測試者可以通過Java類和伺服器進行互動,並且將伺服器端的響應當作文本或者DOM對象進行處理。HttpUnit還提供了一個類比Servlet容器,讓你可以不需要發布Servlet,就可以對Servlet的內部代碼進行測試。本文中作者將詳細的介紹如何使用HttpUnit提供的類完成整合測試。
關鍵詞: httpunit 整合測試
1 HttpUnit簡介
HttpUnit是SourceForge下面的一個開源項目,它是基於JUnit的一個測試架構,主要關注於測試Web應用,解決使用JUnit架構無法對遠程Web內容進行測試的弊端。當前的最新版本是1.5.4。為了讓HtpUnit正常運行,你應該安裝JDK1.3.1或者以上版本。
1.1 工作原理
HttpUnit通過類比瀏覽器的行為,處理頁面架構(frames),cookies,頁面跳轉(redirects)等。通過HttpUnit提供的功能,你可以和伺服器端進行資訊互動,將返回的網頁內容作為普通文本、XML Dom對象或者是作為連結、頁面架構、映像、表單、表格等的集合進行處理,然後使用JUnit架構進行測試,還可以導向一個新的頁面,然後進行新頁面的處理,這個功能使你可以處理一組在一個操作鏈結中的頁面。
1.2 和其他商業工具的對比
商業工具一般使用記錄、回放的功能來實現測試,但是這裡有個缺陷,就是當頁面設計被修改以後,這些被記錄的行為就不能重用了,需要重新錄製才能繼續測試。
舉個例子:如果頁面上有個元素最先的設計是採用單選框,這個時候你開始測試,那麼這些工具記錄的就是你的單項選擇動作,但是如果你的設計發生了變化,比如說我改成了下拉選擇,或者使用文字框接受使用者輸入,這時候,你以前錄製的測試過程就無效了,必須要重新錄製。
而HttpUnit因為關注點是這些控制項的內容,所以不管你的外在表現形式如何變化,都不影響你已確定測試的可重用性。
更多的關於httpunit的資訊請訪問httpunit的首頁 http://httpunit.sourceforge.net/
2 作者的示範環境
系統平台:Windows 2000 Sercver
應用伺服器:深圳金蝶的apusic3.0
開發工具: eclipse 2.1.2
說明: 所有的代碼請下載作者提供的code.jar檔案。
3 HttpUnit安裝、環境配置
3.1 安裝
1. 到HttpUnit的首頁 http://httpunit.sourceforge.net 下載最新的包檔案,當前的最新版本是1.5.4。/
2. 將下載。Zip包解壓縮到c:/httpunit(後面將使用%httpunit_home%引用該目錄)
3.2 環境配置
作者的示範程式都是在eclipse中開發、執行的,所以環境配置都是以eclipse為例,如果你使用其他的開發工具,請根據這些步驟進行環境配置。
1. 啟動eclipse,建立一個java工程
2. 將%httpunit_home%/lib/*.jar; %httpunit_home%/jars/*.jar加入到該java工程的Java build Path變數中
4 如何使用httpunit處理頁面的內容
WebConversation類是HttpUnit架構中最重要的類,它用於類比瀏覽器的行為。其他幾個重要的類是:
WebRequest 模仿客戶請求,通過它可以向伺服器發送資訊
WebResponse 類比瀏覽器擷取伺服器端的響應資訊
4.1 擷取指定頁面的內容
4.1.1 直接擷取頁面內容
System.out.println("直接擷取網頁內容:");
// 建立一個WebConversation執行個體
WebConversation wc = new WebConversation();
// 向指定的URL發出請求,擷取響應
WebResponse wr = wc.getResponse( " http://localhost:6888/HelloWorld.html " );
// 用getText方法擷取相應的全部內容
// 用System.out.println將擷取的內容列印在控制台上
System.out.println( wr.getText() );
4.1.2 通過Get方法訪問頁面並且加入參數
System.out.println("向伺服器發送資料,然後擷取網頁內容:");
//建立一個WebConversation執行個體
WebConversation wc = new WebConversation();
//向指定的URL發出請求
WebRequest req = new GetMethodWebRequest( " http://localhost:6888/HelloWorld.jsp " );
//給請求加上參數
req.setParameter("username","姓名");
//擷取響應對象
WebResponse resp = wc.getResponse( req );
//用getText方法擷取相應的全部內容
//用System.out.println將擷取的內容列印在控制台上
System.out.println( resp.getText() );
4.1.3 通過Post方法訪問頁面並且加入參數
System.out.println("使用Post方式向伺服器發送資料,然後擷取網頁內容:");
//建立一個WebConversation執行個體
WebConversation wc = new WebConversation();
//向指定的URL發出請求
WebRequest req = new PostMethodWebRequest( " http://localhost:6888/HelloWorld.jsp " );
//給請求加上參數
req.setParameter("username","姓名");
//擷取響應對象
WebResponse resp = wc.getResponse( req );
//用getText方法擷取相應的全部內容
//用System.out.println將擷取的內容列印在控制台上
System.out.println( resp.getText() );
大家關注一下上面代碼中打了底線的兩處內容,應該可以看到,使用Get、Post方法訪問頁面的區別就是使用的請求對象不同。
4.2 處理頁面中的連結
這裡的示範是找到頁面中的某一個連結,然後類比使用者的單機行為,獲得它指向檔案的內容。比如在我的頁面HelloWorld.html中有一個連結,它顯示的內容是TestLink,它指向我另一個頁面TestLink.htm. TestLink.htm裡面只顯示TestLink.html幾個字元。
下面是處理代碼:
System.out.println("擷取頁面中連結指向頁面的內容:");
//建立一個WebConversation執行個體
WebConversation wc = new WebConversation();
//擷取響應對象
WebResponse resp = wc.getResponse( " http://localhost:6888/HelloWorld.html " );
//獲得頁面連結化物件
WebLink link = resp.getLinkWith( "TestLink" );
//類比使用者單擊事件
link.click();
//獲得當前的響應對象
WebResponse nextLink = wc.getCurrentPage();
//用getText方法擷取相應的全部內容
//用System.out.println將擷取的內容列印在控制台上
System.out.println( nextLink.getText() );
4.3 處理頁面中的表格
表格是用來控制頁面顯示的常規對象,在HttpUnit中使用數組來處理頁面中的多個表格,你可以用resp.getTables()方法擷取頁面所有的表格對象。他們依照出現在頁面中的順序儲存在一個數組裡面。
[注意] Java中數組下標是從0開始的,所以取第一個表格應該是resp.getTables()[0],其他以此類推。
下面的例子示範如何從頁面中取出第一個表格的內容並且將他們迴圈顯示出來:
System.out.println("擷取頁面中表格的內容:");
//建立一個WebConversation執行個體
WebConversation wc = new WebConversation();
//擷取響應對象
WebResponse resp = wc.getResponse( " http://localhost:6888/HelloWorld.html " );
//獲得對應的表格對象
WebTable webTable = resp.getTables()[0];
//將表格對象的內容傳遞給字串數組
String[][] datas = webTable.asText();
//迴圈顯示表格內容
int i = 0 ,j = 0;
int m = datas[0].length;
int n = datas.length;
while (i<n){
j=0;
while(j<m){
System.out.println("表格中第"+(i+1)+"行第"+(j+1)+"列的內容是:"+datas[j]);
++j;
}
++i;
}
4.4 處理頁面中的表單
表單是用來接受使用者輸入,也可以向使用者顯示使用者已輸入資訊(如需要使用者修改資料時,通常會顯示他以前輸入過的資訊),在HttpUnit中使用數組來處理頁面中的多個表單,你可以用resp.getForms()方法擷取頁面所有的表單對象。他們依照出現在頁面中的順序儲存在一個數組裡面。
[注意] Java中數組下標是從0開始的,所以取第一個表單應該是resp.getForms()[0],其他以此類推。
下面的例子示範如何從頁面中取出第一個表單的內容並且將他們迴圈顯示出來:
System.out.println("擷取頁面中表單的內容:");
//建立一個WebConversation執行個體
WebConversation wc = new WebConversation();
//擷取響應對象
WebResponse resp = wc.getResponse( " http://localhost:6888/HelloWorld.html " );
//獲得對應的表單對象
WebForm webForm = resp.getForms()[0];
//獲得表單中所有控制項的名字
String[] pNames = webForm.getParameterNames();
int i = 0;
int m = pNames.length;
//迴圈顯示表單中所有控制項的內容
while(i<m){
System.out.println("第"+(i+1)+"個控制項的名字是"+pNames+",裡面的內容是"+webForm.getParameterValue(pNames));
++i;
}
5 如何使用httpunit進行測試
5.1 對頁面內容進行測試
httpunit中的這部分測試完全採用了JUnit的測試方法,即直接將你期望的結果和頁面中的輸出內容進行比較。不過這裡的測試就簡單多了,只是字串和字串的比較。
比如你期望中的頁面顯示是中有一個表格,它是頁面中的第一個表格,而且他的第一行第一列的資料應該是顯示username,那麼你可以使用下面的代碼進行自動化測試:
System.out.println("擷取頁面中表格的內容並且進行測試:");
//建立一個WebConversation執行個體
WebConversation wc = new WebConversation();
//擷取響應對象
WebResponse resp = wc.getResponse( " http://localhost:6888/TableTest.html " );
//獲得對應的表格對象
WebTable webTable = resp.getTables()[0];
//將表格對象的內容傳遞給字串數組
String[][] datas = webTable.asText();
//對錶格內容進行測試
String expect = "中文";
Assert.assertEquals(expect,datas[0][0]);
5.2 對Servlet進行測試
除了對頁面內容進行測試外,有時候(比如開發複雜的Servlets的時候),你需要對Servlet本身的代碼塊進行測試,這時候你可以選擇HttpUnit,它可以提供一個類比的Servlet容器,讓你的Servlet代碼不需要發布到Servlet容器(如tomcat)就可以直接測試。
5.2.1 原理簡介
使用httpunit測試Servlet時,請建立一個ServletRunner的執行個體,他負責類比Servlet容器環境。如果你只是測試一個Servlet,你可以直接使用registerServlet方法註冊這個Servlet,如果需要配置多個Servlet,你可以編寫自己的web.xml,然後在初始化ServletRunner的時候將它的位置作為參數傳給ServletRunner的構造器。
在測試Servlet時,應該記得使用ServletUnitClient類作為用戶端,他和前面用過的WebConversation差不多,都繼承自WebClient,所以他們的調用方式基本一致。要注意的差別是,在使用ServletUnitClient時,他會忽略URL中的主機地址資訊,而是直接指向他的ServletRunner實現的類比環境。
5.2.2 簡單測試
本執行個體只是示範如何簡單的訪問Servlet並且擷取他的輸出資訊,例子中的Servlet在接到使用者請求的時候只是返回一串簡單的字串:Hello World!.
1. Servlet的代碼如下:
public class MyServlet extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse resp)
throws IOException
{
PrintWriter out = resp.getWriter();
//向瀏覽器中寫一個字串Hello World!
out.println("<html><body>Hello World!</body></html>");
out.close();
}
}
2. 測試的調用代碼如下:
//建立Servlet的運行環境
ServletRunner sr = new ServletRunner();
//向環境中註冊Servlet
sr.registerServlet( "myServlet", MyServlet.class.getName() );
//建立訪問Servlet的用戶端
ServletUnitClient sc = sr.newClient();
//發送請求
WebRequest request = new GetMethodWebRequest( " http://localhost/myServlet " );
//獲得類比伺服器的資訊
WebResponse response = sc.getResponse( request );
//將獲得的結果列印到控制台上
System.out.println(response.getText());
5.2.3 測試Servlet的內部行為
對於開發人員來說,僅僅測試請求和返回資訊是不夠的,所以HttpUnit提供的ServletRunner模擬器可以讓你對被調用Servlet內部的行為進行測試。和簡單測試中不同,這裡使用了InvocationContext獲得該Servlet的環境,然後你可以通過InvocationContext對象針對request、response等對象或者是該Servlet的內部行為(非服務方法)進行操作。
下面的代碼示範了如何使用HttpUnit類比Servlet容器,並且通過InvocationContext對象,測試Servlet內部行為的大部分工作,比如控制request、session、response等。
//建立Servlet的運行環境
ServletRunner sr = new ServletRunner();
//向環境中註冊Servlet
sr.registerServlet( "InternalServlet", InternalServlet.class.getName() );
//建立訪問Servlet的用戶端
ServletUnitClient sc = sr.newClient();
//發送請求
WebRequest request = new GetMethodWebRequest( " http://localhost/InternalServlet " );
request.setParameter("pwd","pwd");
//獲得該請求的上下文環境
InvocationContext ic = sc.newInvocation( request );
//調用Servlet的非服務方法
InternalServlet is = (InternalServlet)ic.getServlet();
is.myMethod();
//直接通過上下文獲得request對象
System.out.println("request中擷取的內容:"+ic.getRequest().getParameter("pwd"));
//直接通過上下文獲得response對象,並且向用戶端輸出資訊
ic.getResponse().getWriter().write("haha");
//直接通過上下文獲得session對象,控制session對象
//給session賦值
ic.getRequest().getSession().setAttribute("username","timeson");
//擷取session的值
System.out.println("session中的值:"+ic.getRequest().getSession().getAttribute("username"));
//使用用戶端擷取返回資訊,並且列印出來
WebResponse response = ic.getServletResponse();
System.out.println(response.getText());
[注意] 在測試Servlet的之前,你必須通過InvocationContext完成Servlet中的service方法中完成的工作,因為通過newInvocation方法擷取InvocationContext執行個體的時候該方法並沒有被調用。
6 總結
本文中,作者詳細的示範和介紹了如何使用HttpUnit提供的類來進行整合測試,主要實現以下操作:
1. 類比使用者行為向伺服器發送請求,傳遞參數
2. 類比使用者接受伺服器的響應資訊,並且通過輔助類分析這些響應資訊,結合JUnit架構進行測試
3. 使用HttpUnit提供的類比Servler容器,測試開發中的Servlet的內部行為