2005 年 1 月 27 日 本 文將介紹 StrutsTestCase(STC)框架,解釋如何用模擬方式和 Cactus 方式測試示例應(yīng)用程序。作者 Sunil Patil 是 IBM 印度軟件試驗室的開發(fā)人員,他首先將介紹 STC,然后會帶您遍歷設(shè)置使用 STC 和測試各種 Struts 特性的環(huán)境的過程。還將演示如何在 STC 中同時使用 Cactus 和模擬方式。 注意:本文要求讀者熟悉 Struts 框架。 StrutsTestCase(STC)框架是一個開源框架,用來測試基于 Struts 的 Web 應(yīng)用程序。這個框架允許您在以下方面進行測試: - 在
ActionForm 類中的驗證邏輯(validate() 方法)。 - 在
Action 類中的業(yè)務(wù)邏輯(execute() 方法)。 - 動作轉(zhuǎn)發(fā)(Action Forwards)。
- 轉(zhuǎn)發(fā) JSP。
STC 支持兩種測試類型: - Mock 方法 —— 在這種方法中,通過模擬容器提供的對象(
HttpServletRequest 、 HttpServletResponse 和 ServletContext ),STC 不用把應(yīng)用程序部署在應(yīng)用服務(wù)器中,就可以對其進行測試。 - Cactus 方法 —— 這種方法用于集成測試階段,在這種方法中,應(yīng)用程序要部署在容器中,所以可以像運行其他 JUnit 測試用例那樣運行測試用例。
示例應(yīng)用程序 首 先我們將逐步介紹示例 Struts 應(yīng)用程序的創(chuàng)建,這個應(yīng)用程序是測試的基礎(chǔ)。可以用 Struts 自帶的 struts-blank.war 或者自己喜歡的 IDE 來創(chuàng)建示例應(yīng)用程序。示例應(yīng)用程序中有一個登錄頁面,用戶在這里輸入用戶名和口令。如果登錄成功,用戶會被重定向到成功頁面。如果登錄失敗,那么用戶會被 重定向到登錄頁面。 選擇本文頂部或底部的 Code 圖標(biāo)可以得到本文附帶的源代碼。 Login.jsp 頁面 創(chuàng)建登錄頁面,如清單 1 所示:
清單 1. Login.jsp <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <html:html> <HEAD> <%@ page language="java"contentType="text/html; charset=ISO-8859-1"pageEncoding="ISO-8859-1" %> <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <TITLE>Login.jsp</TITLE> </HEAD> <BODY> <html:form action="/login"> <html:errors/> <H3>Login</H3> <TABLE border="0"> <TBODY> <TR> <TH>User Name</TH> <TD><html:text property=‘userName‘ value=‘‘ /></TD> <TR> <TR> <TH>Password</TH> <TD><html:text property=‘password‘ value=‘‘ /></TD> </TR> <TR> <TD><html:submit property="submit" value="Submit" /></TD> <TD><html:reset /></TD> </TR> </TBODY> </TABLE> </html:form> </BODY> </html:html>
| LoginActionForm.java 類 創(chuàng)建 LoginActionForm.java 類,如清單 2 所示:
清單 2. LoginActionForm.java public class LoginActionForm extends ActionForm { public ActionErrors validate( ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (userName == null || userName.length() == 0) errors.add("userName", new ActionError("username.required")); if (password == null || password.length() == 0) errors.add("password", new ActionError("password.required")); if( isUserDisabled(userName)) errors.add("userName",new ActionError("user.disabled")); return errors; } //Query USERDISABLED table to check if user account is disabled public boolean isUserDisabled(String userName) { //SQL logic to check if user account is disabled } }
| 在 validate() 方法中,需要檢測用戶是否輸入了用戶名和口令,因為這些字段是必需的。而且,還需要查詢 USERDISABLED 表,確認用戶的帳戶沒有被禁用。 LoginAction.java 類 接下來,要創(chuàng)建 LoginAction.java 類,如清單 3 所示:
清單 3. LoginAction.java 類 public class LoginAction extends Action { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { if (isValidUser(loginForm.getUserName(), loginForm.getPassword())) { request.getSession().setAttribute( "userName", loginForm.getUserName()); return mapping.findForward("success"); } else { ActionErrors errors = new ActionErrors(); errors.add("userName", new ActionError("invalid.login")); saveErrors(request, errors); return new ActionForward(mapping.getInput()); } } //Query User Table to find out if userName and password combination is right. public boolean isValidUser(String userName, String password) { //SQL Logic to check if username password combination is right } }
| 在這里,execute() 方法用于驗證用戶名和口令是否有效。示例應(yīng)用程序用 USER 表保存用戶名和口令。如果用戶的憑證有效,則會在請求范圍內(nèi)保存用戶名,并把用戶轉(zhuǎn)到登錄成功頁面(Success.jsp)。 struts-config.xml 文件 創(chuàng)建 struts-config.xml 文件,如清單 4 所示:
清單 4. struts-config.xml 文件 <action-mappings> <action path="/login" type="com.sample.login.LoginAction" name="loginForm" scope="request" input="Login.jsp"> <forward name="success" path="/Success.jsp"/> </action> </action-mappings>
| 如果登錄不成功,那么用戶會被重新定向到登錄頁面。 Success.jsp 頁面 創(chuàng)建 Success.jsp 頁面,如清單 15 所示:
清單 5. Success.jsp 頁面 <HTML> <HEAD> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ page language="java" contentType="text/html; %> <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <TITLE>Success.jsp</TITLE> </HEAD> <BODY> <% String userName = (String)session.getAttribute("userName"); %> Login Successful<br/> <P>Welcome: <%=userName%> .</P> </BODY> <HTML>
| 在這里,可從屬性范圍中讀取 userName 屬性,并用它來歡迎已經(jīng)登錄的用戶。
使用模擬對象方式 模擬測試是對應(yīng)用程序進行單元測試的流行方式。如果是初次接觸模擬測試方式,想了解更多的內(nèi)容,那么請參閱參考資料。 設(shè)置模擬方式 要使用模擬方式,必須對示例應(yīng)用程序做少許修改。首先要從編寫模擬測試開始: - 把 strutstest-2.1.*.jar 和 junit3.8.1.jar 添加到 classpath。
- 把 WEB-INF 文件夾添加到 classpath。
- 創(chuàng)建
MockLoginTestAction 類,它擴展了 MockStrutsTestCase 類。 - 運行單元測試用例。
現(xiàn)在就完成了對環(huán)境的設(shè)置,可以開始編寫單元測試用例了。 空的用戶名或口令 首先,需要驗證用戶是否沒有輸入用戶名或口令,然后向用戶顯示適當(dāng)?shù)腻e誤信息,并將用戶重定向到登錄頁面??梢栽?MockLoginTestAction 類中創(chuàng)建 testLoginActionFormError() 方法, 如清單 6 所示:
清單 6. testLoginActionFormError() 方法 public void testLoginActionFormError()throws Exception{ setRequestPathInfo("/login"); actionPerform(); String[] actionErrors = {"username.required","password.required"}; verifyActionErrors(actionErrors); verifyInputForward(); }
| 在編寫 STC 測試用例時,要做的第一件事就是告訴 STC 要測試哪個 ActionMapping 類,在這里要測試 LoginAction ,它被映射到 struts-config.xml 文件中的 "/login" 路徑,因此我們必須調(diào)用 setRequestPathInfo("/login") 。默認情況下,STC 在 /WEB-INF/ 文件夾中查找 struts-config.xml 文件。如果在 classpath 沒有這個文件,就必須用 struts-config.xml 文件的完整路徑調(diào)用 setConfigFile() 。 現(xiàn)在可以執(zhí)行測試用例了。首先要調(diào)用 actionPerform() 方法,把控制權(quán)傳遞給 Struts 框架,執(zhí)行測試用例。一旦控制權(quán)從 actionPeform() 返回,就可以調(diào)用 verifyXXX() 方法,測試對程序的假設(shè)。在示例應(yīng)用程序中,我們想測試一下,在沒有用戶名和口令的時候,調(diào)用 LoginAction 映射是否會利用出錯信息 ActionErrors (用于 username.required 和 password.required )將用戶重定向到登錄頁面。verifyInputForward() 方法檢查這個事務(wù)的結(jié)果是否把用戶重定向到動作映射的輸入屬性指定的頁面,在這個例子中,該頁面是 Login.jsp。 可以用 String 數(shù)組調(diào)用 verifyActionErrors() ,該數(shù)組指出,作為這個事務(wù)的結(jié)果,應(yīng)當(dāng)在請求范圍中設(shè)置哪些 ActionErrors 。我們想設(shè)置 username.required 、password.required 和 ActionErrors ,所以創(chuàng)建了一個 String 數(shù)組來保存這些出錯信息,并把它們發(fā)送給 verifyActionErrors() 方法。 STC 模擬方式如何工作 ActionServlet 在 Struts 框架中是一個控制器 servlet。當(dāng)容器得到請求時,會把請求傳遞給 ActionServlet ,由后者進行所有的請求處理。 STC 背后的基本想法是自行創(chuàng)建 ActionServlet 對象,而不是讓容器來創(chuàng)建它,然后再調(diào)用對象上的適當(dāng)方法。ActionServlet 在初始化時需要 ServletContext 和 ServletConfig 對象,在請求處理時需要 HttpServletRequest 和 HttpServletResponse 對象。STC 創(chuàng)建這些類的模擬對象,并把它們傳遞給 Struts。 MockStrutsTestCase 是一個擴展了 junit.framework.TestCase 類的 JUnit 測試用例,所以每個測試用例都會執(zhí)行 setup() 方法。在 MockStrutsTestCase 對象的 setup() 方法中,STC 創(chuàng)建 ActionServlet 對象和其他必需的模擬對象。 在調(diào)用 setRequestPathInfo() 或 addRequestParameter() 方法時,會調(diào)用模擬 HttpServletRequest 對象的適當(dāng)方法。在 HttpServletRequest 的模擬實現(xiàn)中,會把這條信息保存在適當(dāng)?shù)脑O(shè)置狀態(tài)。所以,如果調(diào)用 addRequestParameter("name","value") ,模擬的 HttpServletRequest 對象會保存它,然后,在 Struts 調(diào)用 request.getParameter("name") 時,用 "value" 作為返回值。 在恰當(dāng)?shù)赝瓿?HttpServletRequest 初始化之后,就可以調(diào)用 actionPerform() 方法把控制權(quán)傳遞給 Struts。actionPerform() 方法調(diào)用 ActionServlet 的 doPost() 方法傳遞 HttpServletRequest 和 HttpServletResponse 的模擬實現(xiàn)。 在 ActionServlet 的 doPost() 方法中,處理請求的方式與其他 Struts 請求的處理方式類似,區(qū)別是直到執(zhí)行 ActionForward JSP 組件之前才停止請求處理。在這個階段,模擬對象的狀態(tài)會被修改,以指出已經(jīng)保存 ActionErrors 或 ActionMessages ,或者指出由此生成的 ActionForward 是什么。 一旦控制權(quán)從 control returns from the actionPerform() 方法返回,就可以調(diào)用適當(dāng)?shù)?verifyXXX() 方法(檢測模擬對象的狀態(tài))來檢查各種假設(shè)是否成立。 測試禁用的用戶 LoginActionForm 類的 isUserDisabled() 方法存在一個問題。在這個方法中,是通過查詢 USERDISABLED 表來找出用戶帳戶是否被禁用。但是在當(dāng)前的環(huán)境下,我們不想把時間浪費在設(shè)置和查詢數(shù)據(jù)庫上。 請記住,我們的目標(biāo)是檢查應(yīng)用程序的 Struts 部分,而不是檢查數(shù)據(jù)庫的交互代碼。為了測試數(shù)據(jù)庫交互代碼,可以從若干個可用工具中選擇一個工具,例如 DBUnit。針對這一情況的最佳方案應(yīng)當(dāng)是創(chuàng)建一個 LoginActionForm 類的子類,并重寫其中的 isUserDisabled() 方法。這個方法將根據(jù)輸入?yún)?shù)的值判斷是返回 true 還是返回 false 。 比如在這個例子中,方法會一直返回 true ,除非用 disabledUser 作為輸入?yún)?shù)調(diào)用它?,F(xiàn)在只應(yīng)當(dāng)在單元測試階段使用這個方法,而主程序 LoginActionForm 不應(yīng)當(dāng)知道這一點。針對這個需求,我創(chuàng)建了 STCRequestProcessor ,它擴展了 RequestProcessor 。它允許向 Action 和 ActionForm 類中插入模擬實現(xiàn)。 要使用 STCRequestProcessor ,需要修改 struts-config.xml,如清單 7 所示:
清單 7. struts-config.xml 文件 <controller> <set-property property="processorClass" value="com.sample.util.STCRequestProcessor"/> </controller> </code>
| 這一行指出 Struts 用 STCRequestProcessor.java 作為 RequestProcessor 。不要忘記,在容器中部署應(yīng)用程序部署時要刪除這些行。 接下來是創(chuàng)建 LoginActionForm 的模擬類,如清單 8 所示:
清單 8. MockLoginActionForm.java 類 public class MockLoginActionForm extends LoginActionForm { public boolean isUserDisabled(String userName) { if (userName != null && userName.equals("disableduser")) return true; return false; } }
| isUserDisabled() 方法檢查用戶名是否為 "disableduser" 。如果是,則應(yīng)當(dāng)返回 true ;否則應(yīng)當(dāng)返回 false 。 接下來要 創(chuàng)建一個測試用例,對禁用用戶進行測試,如清單 9 所示:
清單 9. testDisabledUser() 方法 public void testDisabledUser()throws Exception{ STCRequestProcessor.addMockActionForm("loginForm", "com.sample.login.mock.MockLoginActionForm"); setRequestPathInfo("/login"); addRequestParameter("userName","disableduser"); addRequestParameter("password","wrongpassword"); actionPerform(); verifyInputForward(); String[] userDisabled ={"user.disabled"}; verifyActionErrors(userDisabled); }
| STCRequestProcessor.addMockActionForm() 方法把 MockLoginActionForm 作為 LoginActionForm 的模擬實現(xiàn)插進來。addRequestParameter() 方法設(shè)置用戶名和口令這兩個請求參數(shù)。一旦控制權(quán)從 actionPerform() 返回,就可以調(diào)用 verifyActionErrors() 驗證是否利用 user.disabled 出錯信息將用戶重定向到輸出頁面。 測試無效登錄 測試用例要測試 LoginAction 類的 execute() 方法內(nèi)部的業(yè)務(wù)邏輯。execute() 方法調(diào)用同一個類的 isValidUser() 方法,該方法接下來會查詢 USER 表,查看用戶名和口令組合是否有效?,F(xiàn)在,因為我們不想在測試階段查詢真正的數(shù)據(jù)庫,所以要創(chuàng)建一個 LoginAction 類的模擬子類,重寫 isValidUser() 方法,如清單 10 所示:
清單 10. MockLoginAction.java 類 public class MockLoginAction extends LoginAction { public boolean isValidUser(String userName, String password) { if( userName.equals("ibmuser") && password.equals("ibmpassword")) return true; return false; } }
| 如果用戶名是 "ibmuser" ,口令是 "ibmpassword" ,則 MockLoginAction 類的 isValidUser() 方法將返回 true。調(diào)用 STCRequestProcessor.addMockAction() 方法把 MockLoginAction 插入 LoginAction ,如清單 11 所示:
清單 11. testInvalidLogin() 方法 public void testInvalidLogin()throws Exception{ STCRequestProcessor.addMockActionForm("loginForm", "com.sample.login.mock.MockLoginActionForm"); STCRequestProcessor.addMockAction("com.sample.login.LoginAction", "com.sample.login.mock.MockLoginAction"); setRequestPathInfo("/login"); addRequestParameter("userName","ibmuser"); addRequestParameter("password","wrongpassword"); actionPerform(); String[] invalidLogin ={"invalid.login"}; verifyActionErrors(invalidLogin); verifyInputForward(); }
| 在這個測試用例中,插入了 LoginAction 和 LoginActionForm 的模擬實現(xiàn),避免數(shù)據(jù)庫查詢,接著要設(shè)置用戶名和口令參數(shù)。在控制權(quán)從 actionPerform() 返回之后,就可以檢查是否利用 "invalid.login" 這條出錯信息把用戶重定向到登錄頁面。 測試有效登錄 現(xiàn)在是時候來驗證在用戶輸入正確的用戶名和口令時,是否用成功頁面歡迎用戶,如清單 12 所示:
清單 12. testLoginActionFormError public void testValidLogin() throws Exception{ STCRequestProcessor.addMockActionForm("loginForm", "com.sample.login.mock.MockLoginActionForm"); STCRequestProcessor.addMockAction("com.sample.login.LoginAction", "com.sample.login.mock.MockLoginAction"); setRequestPathInfo("/login"); addRequestParameter("userName","ibmuser"); addRequestParameter("password","ibmpassword"); actionPerform(); verifyNoActionErrors(); verifyForward("success"); }
| 這一代碼段首先在請求參數(shù)中把用戶名設(shè)置為"ibmuser" ,并把口令設(shè)置為 "ibmpassword" ,然后調(diào)用 actionPerform() 。在執(zhí)行 actionPerform() 方法時,需要調(diào)用 verifyForward() 方法,檢查用戶是否被重定向到成功頁面。它還調(diào)用了 verifyNoActionErrors() 方法,以驗證在這個事務(wù)中沒有出現(xiàn) ActionErrors 。
模擬的優(yōu)勢與不足 使用模擬方式有一些優(yōu)勢。這種方式比較快,因為不必為了每個更改而啟動和停止容器。另一方面,因為沒有使用真正的容器,所以可能無法驗證監(jiān)聽器或過濾器帶來的副作用。而且,因為沒有執(zhí)行 ActionForward JSP 組件,所以也無法發(fā)現(xiàn) JSP 中的錯誤。
Cactus 方式 Cactus(容器內(nèi))是集成測試階段的一種流行測試方法。這里不對它進行詳細介紹 Cactus,有關(guān)的更多信息,請參閱參考資料。 Cactus 方式的設(shè)置 要設(shè)置 Cactus,需要將 cactus.1.6.1.jar 和 aspectjrt1.1.1.jar 復(fù)制到 classpath 中。 Cactus 需要在 Web 應(yīng)用程序中配置兩個 servlet,所以必須在 web.xml 文件中聲明它們,如清單 13 所示:
清單 13. web.xml <servlet> <servlet-name<ServletTestRedirector</servlet-name> <display-name<ServletTestRedirector</display-name> <servlet-class<org.apache.cactus.server.ServletTestRedirector</servlet-class> </servlet> <servlet> <servlet-name<ServletTestRunner</servlet-name> <display-name<ServletTestRunner</display-name> <servlet-class<org.apache.cactus.server.runner.ServletTestRunner</servlet-class> </servlet> <servlet-mapping> <servlet-name<ServletTestRedirector</servlet-name> <url-pattern</ServletRedirector</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name<ServletTestRunner</servlet-name> <url-pattern</ServletTestRunner</url-pattern> </servlet-mapping>
| 接下來要創(chuàng)建 cactus.properties 文件,并把它放在 classpath 中,如下所示: cactus.contextURL = http://localhost:9080/sample1 cactus.servletRedirectorName = ServletRedirector
| 本文使用 WebSphere Studio 內(nèi)置的測試環(huán)境來運行測試用例,所以可以從 http://localhost:9080/sample1 訪問示例應(yīng)用程序。請確保把這個路徑修改成指向 Web 應(yīng)用程序?qū)嶋H部署位置的路徑。 接下來要創(chuàng)建一個類,擴展 CactusStrutsTestCase 。因為在模擬和 Cactus 方式中可以使用相同的測試用例,所以可以在這個類中復(fù)制 MockLoginActionTest 的內(nèi)容。在選中的容器中構(gòu)建并部署這個應(yīng)用程序。 最后,把 jdbc/ds1 配置成數(shù)據(jù)源。 STC Cactus 方法的工作原理 在 使用 Cactus 測試應(yīng)用程序的時候,必須把應(yīng)用程序部署在 Web 容器中,還要在容器外面用 JUnit 測試用例的形式運行 Cactus 測試用例。在運行 Cactus 單元測試時,它會為類中的每個測試用例方法都創(chuàng)建并執(zhí)行一個針對 URL 的HTTP 請求,URL 由 cactus.properties 文件中 cactus.contextURL 參數(shù)指定。 在示例應(yīng)用程序的例子中,在執(zhí)行 testDisableUser 時,會創(chuàng)建并執(zhí)行以下請求: http://localhost:9080/sample1/ServletRedirector?Cactus_TestMethod=testDisabledUser&Cactus_TestClass= com.sample.test.CactusLoginActionTest&Cactus_AutomaticSession=true&Cactus_Service=CALL_TEST
| 這個請求會調(diào)用 ServletTestRedirector servlet(作為示例 Web 應(yīng)用程序的一部分部署)。在 ServletTestRedirector 中,Cactus 從 Cactus_TestClass 請求參數(shù)中查找測試用例類的名稱,并調(diào)用 Cactus_TestMethod 參數(shù)指定的方法。在執(zhí)行這個方法之后,就會以 HTTP 響應(yīng)的方式把結(jié)果返回 Cactus 測試類,這個類將執(zhí)行一個外部容器。 此外,在 testDisabledUser() 方法中的 CactusStrutsTestCase 的容器內(nèi)(in-container)版本得到控制時(在本文的示例中是 CactusLoginActionTest ),STC 會調(diào)用 actionPerform() 方法,該方法將創(chuàng)建 ActionServlet 、ServletContext 和 ServletConfig 對象的實例。STC 還在包裝器中包裝了當(dāng)前的請求和響應(yīng)。然后它調(diào)用 ActionServlet 的方法 doPost() ,該方法使用的參數(shù)是這些包裝的 ServletRequest 和 ServletResponse 對象。然后 Struts 會像平常一樣處理請求。 通過使用 Cactus 方式,就可以調(diào)用 processRequest(true) 方法告訴 STC 驗證轉(zhuǎn)發(fā) JSP,從而執(zhí)行和測試轉(zhuǎn)發(fā)的 JSP,以確保不會拋出任何編譯和運行時錯誤。 一旦控制權(quán)從 actionPerform() 返回,就可以調(diào)用各種 verifyXXX() 方法檢驗假設(shè)是否成立。 測試轉(zhuǎn)發(fā) JSP 的錯誤 修改 testVaidLogin() 方法,測試 Success.jsp,保證它沒有編譯時錯誤或運行時錯誤, 如清單 14 所示:
清單 14. testValidLogin() 方法 public void testValidLogin() throws Exception{ STCRequestProcessor.addMockActionForm("loginForm","com.sample.login.mock.MockLoginActionForm"); STCRequestProcessor.addMockAction("com.sample.login.LoginAction","com.sample.login.mock.MockLoginAction"); processRequest(true); setRequestPathInfo("/login"); addRequestParameter("userName","ibmuser"); addRequestParameter("password","ibmpassword"); actionPerform(); verifyNoActionErrors(); verifyForward("success"); }
| 還要修改 Success.jsp,添加以下幾行,讓它拋出 RunTimeException 異常: <% throw new RuntimeException("test error"); %>
| 現(xiàn)在,當(dāng)運行這個測試用例時,testValidLogin() 會創(chuàng)建并執(zhí)行數(shù)據(jù)庫查找,檢查用戶帳戶是否禁用,用戶名和口令是否有效。如果測試失敗,則表明在執(zhí)行 Success.jsp 時遇到了運行時錯誤。
Cactus 的優(yōu)勢與不足 使用 Cactus 當(dāng)然有優(yōu)勢,但是困難也不少。從正面來說,它允許測試 JSP 頁面的編譯和運行時錯誤,還允許測試數(shù)據(jù)訪問代碼。從負面來說,這種方式要求把應(yīng)用程序部署在容器中,然后每做一次修改都要啟動和停止容器,這使 Cactus 成為一種較慢的模擬方式。
結(jié)束語 單 元測試提供了很多好處。除了讓人確信代碼按照設(shè)計的方式工作之外,測試還是造就優(yōu)秀文檔的原因。而且,在設(shè)計類和接口時,單元測試還提供了一個優(yōu)秀的反饋 機制。最后,單元測試對于管理變化也很有幫助。如果在對代碼進行更改之后,代碼通過了所有單元測試,那么就可以確信這些更改是安全的。 不 幸的是,許多開發(fā)人員放棄了單元測試,因為他們要花太多時間來編寫測試代碼。但是通過使用 STC 的模擬方式,可以把通?;ㄙM在設(shè)置特定領(lǐng)域(例如數(shù)據(jù)庫和容器)開發(fā)環(huán)境上的大量時間節(jié)省下來。因為不必每次都重新啟動和停止容器,所以 STC 還有助于迅速測試變化。一旦代碼穩(wěn)定下來,能夠通過所有測試用例,那么只要改變一下測試用例的父類,就可以將它用于集成測試。在集成階段使用 Cactus 還允許您自動化集成測試過程。
|