
很多人學會JUnit後,就希望能在程式開發時使用,卻發現在web中根本沒辦法用,因為web程式
有太多是需要container啟動才能執行的。基本上JUnit適合用在J2SE程式的測試,在J2EE方面則力有未
逮,這時候就是Cactus粉墨登場的時候了。Cactus也是由apache所開發,是架構於JUnit之上,所以在學
習Cactus之前,先學會JUnit仍是有幫助的。接下來我們將說明Cactus如何測試servlet及jsp程式,測試時
我使用的container是Tomcat 4.1.30。
- 概念解說
上圖是Cactus的架構圖,這裡做個簡單說明:
YYYTestCase = ( ServletTestCase | FilterTestCase | JspTestCase )
XXX是test case的名稱,每個YYYTestCase包含數個test case。
- 圖中標號1~8是執行的順序,當測試開始時TestRunner會產生TestCase實例,並呼叫裡面的runTest method
(YYYTestCase.runTest() method ), runTest method會尋找TestCase裡的begin()
method及beginXXX() method並依序執行。
- YYYTestCase.runTest() method接著開啟一個連線到Redirector
Proxy的Http連線,所有在beginXXX() method, 中設定的request參數 (HTTP headers, HTTP
parameters, ...) 將會被設定在HTTP request。
- Redirector
Proxy再產生一個TestCase實例,並依序呼叫setUP()、testXXX()、tearDown(),這些method的用法
與JUnit的用法相同,需注意的是這時候由Redirector
Proxy產生的HttpServletRequest、ServletConfig、ServletContext… 現在可以使用了。
- Redirector Proxy收集測試結果,並將測試結果以HTTP傳回給YYYTestCase。
- YYYTestCase執行endXXX()並顯示結果,在測試完成之後,YYYTestCase()會呼叫end() method。
- 在這整個測試流程裡,一般client要傳給server的參數會寫在beginXXX()
method,server端會在testXXX() method裡作測試, client則在endXXX() method看測試結果。
- 範例程式
在開始使用Cactus測試程式之前,我們先寫個登入的功能,接下來才以Cactus來測試這個功能是否正常, 下圖是登入功能的圖示。
- index.jsp
<HTML>
<HEAD>
<%@ page language="java"
contentType="text/html; charset=BIG5" pageEncoding="BIG5" %>
<META http-equiv="Content-Type" content="text/html; charset=BIG5">
<TITLE>首頁</TITLE>
</HEAD>
<BODY>
<form action="/UnitTest/LoginServlet">
登入名稱: <input type="text" name="username"><br>
登入密碼: <input type="password" name="password"><br>
<input type="submit" value="登入">
</form>
</BODY>
</HTML>
- LoginServlet.java
package tw.idv.idealist.cactus;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (isValidUser(req)) {
String username = req.getParameter("username");
req.setAttribute("username", username);
RequestDispatcher rd = req.getRequestDispatcher("/welcome.jsp");
rd.forward(req, resp);
}
else {
//do something
}
}
public boolean isValidUser(HttpServletRequest req) {
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username.equals("steven") && password.equals("1234")) {
return true;
}
else {
return false;
}
}
}
- welcome.jsp
<HTML>
<HEAD>
<%@ page language="java" contentType=
"text/html; charset=BIG5" pageEncoding="BIG5" %>
<META http-equiv="Content-Type" content="text/html; charset=BIG5">
<TITLE>歡迎頁</TITLE>
</HEAD>
<BODY>
Hello, <%= request.getAttribute("username") %>!
</BODY>
</HTML>
上面的程式,執行後輸入登入名稱steven,登入密碼1234後,結果會如下:
- 安裝設定
首先到Cactus的官方網站下載並解開。以下安裝Cactus的目錄以$Cactus表示。首先將[$Cactus/lib]目錄下的
commons-logging-xxx.jar、aspectjrt-xxx.jar、cactus-
xxx.jar、commons-httpclient-xxx.jar與junit-xxx.jar放到web程式
下的WEB-INF/lib目錄下,再將cactus-report.xsl放置在web程式的根目錄下。接下來在WEB-INF/web.xml加入
如下內容:
FilterRedirector、ServletRedirector、JspRedirector是測試Filter、Servlet、Jsp時的Redirector
Proxy,如果
你只要測試其中一項,可以選擇性加入即可,如果要用到JspRedirector要記得將jspRedirector.jsp放到根目錄。
<filter>
<filter-name>FilterRedirector</filter-name>
<filter-class>org.apache.cactus.server.FilterTestRedirector
</filter-class>
</filter>
<servlet>
<servlet-name>ServletRedirector</servlet-name>
<servlet-class>org.apache.cactus.server.ServletTestRedirector
</servlet-class>
</servlet>
<servlet>
<servlet-name>JspRedirector</servlet-name>
<jsp-file>/jspRedirector.jsp</jsp-file>
</servlet>
<servlet>
<servlet-name>ServletTestRunner</servlet-name>
<servlet-class>org.apache.cactus.server.runner.ServletTestRunner
</servlet-class>
<init-param>
<param-name>xsl-stylesheet</param-name>
<param-value>cactus-report.xsl</param-value>
</init-param>
</servlet>
<filter-mapping>
<filter-name>FilterRedirector</filter-name>
<url-pattern>/FilterRedirector</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>ServletRedirector</servlet-name>
<url-pattern>/ServletRedirector</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JspRedirector</servlet-name>
<url-pattern>/JspRedirector</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletTestRunner</servlet-name>
<url-pattern>/ServletTestRunner</url-pattern>
</servlet-mapping>
測試servlet
接下來我們要撰寫測試案例,用來測試LoginServlet,如前面概念解說所述,beginValidUser會先被執行,
client要傳給server的參數在此加入,到了server端,TestRunner會去找名稱相同的method即testValidUser來執
行,在此我們對LoginServler做驗證。程式及執行結果如下:
- LoginServletTest.java
package tw.idv.idealist.cactus;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import org.apache.cactus.*;
public class LoginServletTest extends ServletTestCase {
public void beginValidUser(WebRequest webreq) {
webreq.addParameter("username", "steven");
webreq.addParameter("password", "1234");
}
public void testValidUser() {
LoginServlet login = new LoginServlet();
assertTrue(login.isValidUser(request));
}
}
- 執行結果
在瀏覽器上打入http://localhost/UnitTest/ServletTestRunner?suite=tw.idv.idealist.cactus.LoginServletTest&transform=yes
將會呈現以下的測試結果: (UnitTest是專案名稱)
測試JSP
所謂對JSP測試,就是對JSP所顯示出來的網頁內容做測試,由概念解說的圖可以了解,如果要知道JSP
的網頁內容應該是在client端的endXXX() method接收顯示出的來內容並做檢查。
- use ServletTestCase
package tw.idv.idealist.cactus;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import org.apache.cactus.*;
public class LoginServletTest extends ServletTestCase {
public void beginValidUser(WebRequest webreq) {
webreq.addParameter("username", "steven");
webreq.addParameter("password", "1234");
}
public void testValidUser() {
LoginServlet login = new LoginServlet();
assertTrue(login.isValidUser(request));
}
public void testWelcomePage() throws ServletException, IOException {
request.setAttribute("username", "steven");
RequestDispatcher rd = request.getRequestDispatcher("/welcome.jsp");
rd.forward(request, response);
}
public void endWelcomePage(WebResponse webResponse) {
assertTrue(webResponse.getText().indexOf("Hello, steven!") > 0);
}
}
- Results (I)
在瀏覽器上打入http://localhost/UnitTest/ServletTestRunner?suite=tw.idv.idealist.cactus.LoginServletTest&transform=yes 將會呈現以下的測試結果:
- use JspTestCase
另一個測試的方法是繼承JspTestCase,測試程式如下:
package tw.idv.idealist.cactus;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.cactus.*;
public class LoginPageTest extends JspTestCase {
public void testWelcomePage()
throws ServletException, IOException {
request.setAttribute("username", "steven");
pageContext.forward("welcome.jsp");
}
public void endWelcomePage(WebResponse webResponse) {
assertTrue(webResponse.getText().indexOf("Hello, steven!") >);
}
}
- Results (II)
在瀏覽器上打入http://localhost/UnitTest/ServletTestRunner?suite=tw.idv.idealist.cactus.LoginPageTest&transform=yes 將會呈現以下的測試結果:
|