小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

j2ee開發(fā)平臺(tái)的軟件測試技術(shù)

 duduwolf 2005-07-23
 

J2EE開發(fā)平臺(tái)的軟件測試技術(shù)

作者:佚名(來自:cybercorlin.net 

    前言 - 以測試為導(dǎo)向的軟件開發(fā)流程

  軟件開發(fā)流程的新興觀念是將軟件測試的角色,提升為系統(tǒng)開發(fā)時(shí)每一個(gè)階段都必須要持續(xù)且反復(fù)進(jìn)行的重要任務(wù),確保每一個(gè)階段都能及早發(fā)現(xiàn)潛藏于系統(tǒng)內(nèi)的危險(xiǎn)因子。當(dāng)某一個(gè)階段的測試結(jié)果無法達(dá)到預(yù)期的要求時(shí),就必須回溯到之前的開發(fā)階段,再次分析和審核,這種過程稱之為重構(gòu)(Refactoring)。配合重構(gòu)的機(jī)制,讓系統(tǒng)的品質(zhì)都能夠在嚴(yán)密的測試監(jiān)控下持續(xù)成長。不過由于網(wǎng)絡(luò)時(shí)代的革命興起之后,軟件系統(tǒng)的架構(gòu)變得更為復(fù)雜,相對(duì)的軟件測試的發(fā)展也更顯得重要。
     J2EE平臺(tái)內(nèi)的軟件測試
   XP只定義了兩種測試的層級(jí),第一種層級(jí)是「單元測試」,因?yàn)閱卧獪y試的用意是為了檢驗(yàn)程序代碼是否合乎邏輯,而且是針對(duì)系統(tǒng)內(nèi)部的模塊來測試,因此又可以稱做為程序邏輯測試(Code Logic Testing)。為了因應(yīng)不同的應(yīng)用程序開發(fā)平臺(tái)的特殊架構(gòu),在J2EE的平臺(tái)里,還發(fā)展出與J2EE Container 緊密結(jié)合的整合測試(Integration Testing)。
   另一種層級(jí)是接受度測試(Acceptance Testing),又稱作功能測試(Functional Testing)。在軟件測試中還有一個(gè)大家常聽到的是效能測試(Performance Testing)。由于效能測試與客戶的需求是密不可分,所以將它歸類為接受度測試的延伸應(yīng)用。最后歸納起來,一個(gè)J2EE平臺(tái)可能所需要的測試流程,以及測試之間的關(guān)系,如圖一所示。
                        
  在Web層內(nèi)軟件測試的概念與流程,如圖二所示,其中鍵頭旁的數(shù)字符號(hào)代表著整個(gè)測試流程的執(zhí)行步驟。首先先準(zhǔn)備好受測數(shù)據(jù)與受測系統(tǒng)之后,借著虛擬瀏覽器來發(fā)出request,向受測系統(tǒng)取得包裹著HTML code的response。然后再利用測試平臺(tái)來協(xié)助我們進(jìn)行受測數(shù)據(jù)與預(yù)期值的比對(duì)工作。當(dāng)比對(duì)后所回報(bào)的結(jié)果都是正確無誤時(shí),代表著受測系統(tǒng)的功能可以正常運(yùn)作了。圖中的測試平臺(tái)與虛擬瀏覽器在測試中扮演著關(guān)鍵的角色。
                 
    雖然發(fā)展測試平臺(tái)的概念已經(jīng)行之有年了,然而具備有可延伸且開放式架構(gòu)的測試平臺(tái)并不多,其中OpenSource社群以Java開發(fā)出來的JUnit,是極具代表性的測試平臺(tái)。

1. 單元測試平臺(tái)─ JUnit

   JUnit平臺(tái)的設(shè)計(jì)架構(gòu)是采用了命令(Command)和復(fù)合(Composite)兩種設(shè)計(jì)模式(Design Pattern)做為關(guān)鍵的組成架構(gòu)。在JUnit平臺(tái)中的核心類別是TestCase,而每一個(gè)TestCase代表著一個(gè)命令對(duì)象。TestCase包含數(shù)個(gè)test method,用來測試被測類別內(nèi)public method的產(chǎn)出對(duì)象與預(yù)期的結(jié)果是否相同。在JUnit平臺(tái)內(nèi)有提供數(shù)種用來協(xié)助比對(duì)的assert method。
   JUnit平臺(tái)里還有另一個(gè)核心類別是TestSuite,而每一個(gè)TestSuite代表著一個(gè)復(fù)合的對(duì)象。一個(gè)TestSuite可以由數(shù)個(gè)TestCase或是數(shù)個(gè)TestSuite組成,因此可以根據(jù)測試的需求,拼湊出多個(gè)的TestSuite。整個(gè)JUnit測試平臺(tái)的組成架構(gòu),如圖三所示。在了解了JUnit平臺(tái)的架構(gòu)之后,我們便可以運(yùn)用JUnit平臺(tái)來發(fā)展受測系統(tǒng)的整合測試與功能測試。

                        
代碼實(shí)例:
import junit.framework.*;
import java.util.Vector;
public class VectorTest extends TestCase {
protected Vector fEmpty;
protected Vector fFull;
public VectorTest(String name) {
super(name);
}
public static void main (String[] args) {
junit.textui.TestRunner.run (suite());
}
protected void setUp() {
fEmpty= new Vector();
fFull= new Vector();
fFull.addElement(new Integer(1));
fFull.addElement(new Integer(2));
fFull.addElement(new Integer(3));
}
public static Test suite() {
return new TestSuite(VectorTest.class);
}
public void testCapacity() {
int size= fFull.size();
for (int i= 0; i < 100; i++)
fFull.addElement(new Integer(i));
assertTrue(fFull.size() == 100+size);
}
public void testClone() {
Vector clone= (Vector)fFull.clone();
assertTrue(clone.size() == fFull.size());
assertTrue(clone.contains(new Integer(1)));
}
public void testContains() {
assertTrue(fFull.contains(new Integer(1)));
assertTrue(!fEmpty.contains(new Integer(1)));
}
public void testElementAt() {
Integer i= (Integer)fFull.elementAt(0);
assertTrue(i.intValue() == 1);
try {
Integer j= (Integer)fFull.elementAt(fFull.size());
} catch (ArrayIndexOutOfBoundsException e) {
return;
}
fail("Should raise an ArrayIndexOutOfBoundsException");
}
public void testRemoveAll() {
fFull.removeAllElements();
fEmpty.removeAllElements();
assertTrue(fFull.isEmpty());
assertTrue(fEmpty.isEmpty());
}
public void testRemoveElement() {
fFull.removeElement(new Integer(3));
assertTrue(!fFull.contains(new Integer(3)) );
}
}
import junit.framework.*;
import junit.runner.BaseTestRunner;
public class AllTests {
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
public static Test suite() {
TestSuite suite= new TestSuite("Framework Tests");
suite.addTestSuite(ExtensionTest.class);
suite.addTestSuite(TestCaseTest.class);
suite.addTest(SuiteTest.suite()); suite.addTestSuite(ExceptionTestCaseTest.class);
suite.addTestSuite(TestListenerTest.class);
suite.addTestSuite(ActiveTestTest.class);
suite.addTestSuite(AssertTest.class);
suite.addTestSuite(StackFilterTest.class);
suite.addTestSuite(SorterTest.class);
suite.addTestSuite(RepeatedTestTest.class);
suite.addTestSuite(TestImplementorTest.class);
if (!BaseTestRunner.inVAJava()) {
suite.addTestSuite(TextRunnerTest.class);
if (!isJDK11())
suite.addTest(new TestSuite(TestCaseClassLoaderTest.class));
}
return suite;
}
static boolean isJDK11() {
String version= System.getProperty("java.version");
return version.startsWith("1.1");
}
}

2 整合測試的觀念與Cactus應(yīng)用

   整合測試提供了J2EE Container的環(huán)境,可以快速輕易地檢驗(yàn)出Domain Object與J2EE Container的互動(dòng)行為是否合乎邏輯。因此整合測試的對(duì)象是以一個(gè)EJB、Servlet或是JSP的程序代碼為基本單元。Open Source社群的Jakarta計(jì)劃中的子計(jì)劃Cactus,即是為了實(shí)作整合測試用的平臺(tái)而誕生的。
   Cactus基本上也是延伸JUnit平臺(tái)而發(fā)展出來的,因此它除了原有基本的method之外,還提供了可以用來模擬瀏覽器的內(nèi)部行為的beingxxx( )和endxxx( )的method。這兩個(gè)method來這些method的執(zhí)行順序和與Web Container互動(dòng)的行為模式,如圖四所示。
                        
  我們利用beginxxx( )來設(shè)定要傳遞給受測對(duì)象的字符串參數(shù)。執(zhí)行完beginxxx( )后,會(huì)發(fā)出request將參數(shù)名稱與參數(shù)值傳遞到Web Container。TestCase會(huì)執(zhí)行setUp( ),將受測對(duì)象所需要的對(duì)象環(huán)境建立起來,接著在testxxx( )執(zhí)行存取受測對(duì)象的動(dòng)作。當(dāng)存取受測對(duì)象的動(dòng)作執(zhí)行完后,便可以檢驗(yàn)受測對(duì)象可能存放在session的產(chǎn)出物。然后在Web Container會(huì)執(zhí)行釋放資源的動(dòng)作,然后將response回傳到Client端。最后在Client端執(zhí)行endxxx( )來進(jìn)行比對(duì)HTML code是否和預(yù)期值相同,執(zhí)行完endxxx()時(shí)也代表一個(gè)整合測試的結(jié)束。將這五個(gè)method所執(zhí)行的功能匯整如表一所示。
  雖然Cactus架構(gòu)提供了受測對(duì)象產(chǎn)出物與預(yù)期結(jié)果的比對(duì)功能,但是當(dāng)回傳的HTML code的內(nèi)容過于龐大復(fù)雜時(shí),反而不利于比對(duì)的工作。因此采用了一個(gè)實(shí)用性的做法。此做法是在JSP或servlet欲產(chǎn)出的HTML code的程序代碼里,于關(guān)鍵的卷標(biāo)內(nèi)添加ID這種屬性。當(dāng)endxxx( )要進(jìn)行比對(duì)前,先讀取記載著ID屬性值與預(yù)期值的外部數(shù)據(jù)文件,再透過DOM的存取機(jī)制來取得HTML code,便能夠快速地比對(duì)關(guān)鍵的數(shù)據(jù)。不僅可以將比對(duì)的工作模塊化,更能夠在不需要重新編譯測試碼的情形下,隨時(shí)變更預(yù)期值。讀者們?nèi)粲杏龅较嗨频膯栴}時(shí),不妨可以采用與相同的策略來解決。
   整合測試不同于單元測試,雖然減低了撰寫測試碼的困難度,但也因?yàn)镈omain Object與J2EE Container的結(jié)合,而不能為Domain Object提供單純的測試環(huán)境。因此若有其它的測試可以單純地檢驗(yàn)整個(gè)系統(tǒng),便可以彌補(bǔ)整合測試的不足。功能測試即是扮演這樣的一個(gè)角色。
配置信息與代碼實(shí)例:
<servlet>
<servlet-name>ServletRedirector</servlet-name>
<servlet-class>
org.apache.cactus.server.ServletTestRedirector
</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1 used for testing</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>ServletTestRunner</servlet-name>
<servlet-class>
org.apache.cactus.server.runner.ServletTestRunner
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletRedirector</servlet-name>
<url-pattern>/ServletRedirector</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletTestRunner</servlet-name>
<url-pattern>/ServletTestRunner</url-pattern>
</servlet-mapping>
實(shí)例testcase:
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;
public class TestSampleServlet extends ServletTestCase
{
public TestSampleServlet(String theName)
{
super(theName);
}
public static Test suite()
{
return new TestSuite(TestSampleServlet.class);
}
public void beginSaveToSessionOK(WebRequest webRequest)
{
webRequest.addParameter("testparam", "it works!");
}
public void testSaveToSessionOK()
{
SampleServlet servlet = new SampleServlet();
servlet.saveToSession(request);
assertEquals("it works!", session.getAttribute("testAttribute"));
}
}
 
 
 
 

3 業(yè)務(wù)邏輯測試與StrutsTestcase應(yīng)用

      struts的使用越來越廣泛,但是并沒有合適測試框架與之對(duì)應(yīng).cactus, httpunit雖然都可以測試jsp,servlet,但基于struts框架的應(yīng)用程序的測試依然比較麻煩。
      不過,StrutsTestCase的出現(xiàn)多少解決了些問題,下面主要講講StrutsTestCase的應(yīng)用。和其他的JSP/SERVLET測試框架一樣,StrutsTestCase也有兩種測試結(jié)構(gòu),一種是Mock結(jié)構(gòu),另一種是利用Cactus的結(jié)構(gòu)。
      因?yàn)镾trutsTestCase也是基于junit上開發(fā)的,所以它的使用方法也類似于junit.可以參考他的例子和api.
      可惜的是StrutsTestCase例子里沒有使用ant,因此它的運(yùn)行較讓人頭痛,特別是有關(guān)配置文件的處理。StrutsTestCase在運(yùn)行時(shí)必須能夠找到struts-config.xml和web.xml文件,默認(rèn)的位置是web-inf/目錄下,所以web-inf目錄要存在于classpath或者在運(yùn)行的時(shí)候指定。例如:我的位于d:/struts-test/下,struts-config.xml和web.xml位于d:/struts-test/webapp/WEB-INF/下,那么在運(yùn)行測試的時(shí)候應(yīng)當(dāng)把d:/struts-test/webapp路徑放到classpath里。如果我的struts-config.xml不在/web-inf目錄里,而是在/web-inf/conf/目錄下,那么就須調(diào)用setConfigFile(String path)方法,按照剛才的情況,
public void testSuccessfulLogin() {
setRequestPathInfo("/login"); addRequestParameter("username","deryl"); addRequestParameter("password","radar");
actionPerform();
verifyForward("success"); }
public void testFailedLogin() {
addRequestParameter("username","deryl");
addRequestParameter("password","express");
setRequestPathInfo("/login");
actionPerform();
verifyForward("login");
}
public void setUp() throws Exception {
super.setUp() ;
setConfigFile("/WEB-INF/conf/struts-config.xml") ;
}
 
 

4 功能測試的觀念與HttpUnit應(yīng)用

  以UML的術(shù)語來說,功能測試的對(duì)象是檢驗(yàn)Use Case所規(guī)范的行為,測試系統(tǒng)是否符合所需要的功能,是否能達(dá)到使用者的需求?而單元測試的對(duì)象是檢驗(yàn)對(duì)象Classes Diagram與Sequence Diagram所描述的關(guān)系與行為,測試單元是否執(zhí)行正確,是否符合程序邏輯?。每當(dāng)完成一個(gè)階段性的功能測試,也代表著完成了一部分的系統(tǒng)實(shí)作。
   Open Source社群的HttpUnit API套件,即是為了功能測試而發(fā)展出來的。HttpUnit是以Java撰寫出來的虛擬瀏覽器,用來模擬瀏覽器的內(nèi)部行為。前一節(jié)所提到的Cactus檢驗(yàn)HTML code的機(jī)制,也是采用HttpUnit來完成的。
   除此之外,HttpUnit還可以結(jié)合JUnit平臺(tái)撰寫測試碼來檢驗(yàn)回傳的網(wǎng)頁內(nèi)容是否與預(yù)期結(jié)果相符合。HttpUnit平臺(tái)的運(yùn)作機(jī)制是建構(gòu)在Http標(biāo)準(zhǔn)通訊協(xié)議之下,藉由模擬使用者瀏覽網(wǎng)站時(shí),所發(fā)出的以對(duì)象的形式封裝的request訊號(hào),將其送至到目的網(wǎng)站,然后等到該網(wǎng)站處理完此request之后,便將同樣以對(duì)象形式封裝的response訊號(hào)回傳給HttpUnit。
   由于HttpUnit所接收的是標(biāo)準(zhǔn)HTTP協(xié)議的response對(duì)象,因此不論該網(wǎng)站是靜態(tài)網(wǎng)頁語言或是用任何的動(dòng)態(tài)服務(wù)器端語言寫成的,都可以透過HttpUnit來模擬網(wǎng)站瀏覽的行為并且取得標(biāo)準(zhǔn)的HTML code。
   市面上也有提供功能測試用的預(yù)錄播放軟件,可以事先錄下網(wǎng)站瀏覽的步驟,然后反復(fù)地播放預(yù)錄好的流程,最后回報(bào)測試的數(shù)據(jù)給測試人員,供測試人員進(jìn)行分析,大大節(jié)省撰寫測試碼的負(fù)擔(dān)。然而此類軟件有以下的缺點(diǎn):
1. 當(dāng)網(wǎng)站設(shè)計(jì)的復(fù)雜度越高,瀏覽的分支流程越多,預(yù)錄好的流程便無法作有效的模塊化管理。
2. 預(yù)錄播放軟件雖然有提供記錄瀏覽步驟的script或是XML文件,雖然這些指令碼可以重復(fù)利用,然而若無法提供有效的偵錯(cuò)機(jī)制,一旦安插了錯(cuò)誤的程序,反而容易造成無法預(yù)期的錯(cuò)誤產(chǎn)生。
3. 測試人員需要重新學(xué)習(xí)專屬于預(yù)錄播放軟件的script語言或是XML文件語法,無法從既有熟悉的程序語言來編寫瀏覽網(wǎng)站的程序。
4. 當(dāng)網(wǎng)站的操作接口時(shí)常為了需求而新增或是修改原有的互動(dòng)設(shè)計(jì)時(shí),必須重新錄制新的瀏覽網(wǎng)站的程序,而無法重復(fù)利用。
   HttpUnit解決了軟件開發(fā)人員以上的困擾。HttpUnit是一種黑箱作業(yè)形式的測試工具,因此我們只要專注如何在JUnit平臺(tái)上撰寫模擬瀏覽器行為的測試碼即可。HttpUnit內(nèi)的method執(zhí)行順序和與Web Container互動(dòng)的行為模式,如圖五所示,箭頭符號(hào)旁所標(biāo)示的數(shù)字,代表著這些method的執(zhí)行順序。
 
   當(dāng)我們?cè)趕etup( )設(shè)定好受測的網(wǎng)址與相關(guān)的環(huán)境后,setUp( )會(huì)執(zhí)行向受測網(wǎng)址進(jìn)行存取的動(dòng)作。當(dāng)存取動(dòng)作完成時(shí),會(huì)將response回傳至Client端。此時(shí)可以在testxxx( )做HTML code和預(yù)期值比對(duì)的工作。最后在Client端執(zhí)行釋放資源的動(dòng)作,執(zhí)行完tearDown()時(shí)也代表一個(gè)功能測試的完成。將這三個(gè)method所執(zhí)行的功能匯整如表二所示。
      雖然HttpUnit提供強(qiáng)大的仿真功能,但是HttpUnit本身還是存在兩個(gè)缺點(diǎn)。第一,當(dāng)HttpUnit結(jié)合JUnit平臺(tái)做測試時(shí),由于HttpUnit存取HTML code的方式與HTML內(nèi)部的文件結(jié)構(gòu)的關(guān)聯(lián)過于緊密,因此當(dāng)網(wǎng)頁版面需要變動(dòng)時(shí),也需要修改相對(duì)應(yīng)的測試碼。對(duì)于這樣的困擾,采用了與Cactus檢測HTML code同樣的改良策略,來達(dá)到快速比對(duì)而不用調(diào)整測試碼的好處。
   第二,在HttpUnit與JUnit平臺(tái)結(jié)合做測試的情況時(shí),由于JUnit特殊的運(yùn)作機(jī)制,無法記住每一個(gè)已經(jīng)瀏覽過的網(wǎng)址狀態(tài),因此當(dāng)某個(gè)受測網(wǎng)址與其它網(wǎng)址的依存性強(qiáng)時(shí),若要回傳正確的瀏覽狀態(tài)時(shí),必須要用遞歸記憶的方式來達(dá)成。例如要存取第二個(gè)網(wǎng)頁必須記住第一個(gè)網(wǎng)頁的狀態(tài),存取第三個(gè)網(wǎng)頁要記住第一個(gè)和第二個(gè)網(wǎng)頁的狀態(tài),同理存取第n個(gè)網(wǎng)頁時(shí)需要記住第一個(gè)網(wǎng)頁到n-1個(gè)網(wǎng)頁,這樣的做法不易將測試碼模塊化,如圖六所示。
 
       于是利用了HttpUnit本身也可以寫成獨(dú)立運(yùn)作的程序代碼的特性,寫成一個(gè)瀏覽網(wǎng)站步驟的仿真器。然后利用JUnit的setUp( )來存取受測網(wǎng)站的瀏覽狀態(tài),便可以在testxxx( )取得正確的網(wǎng)頁狀態(tài)來進(jìn)行比對(duì)的工作,經(jīng)過模塊化后的HttpUnit測試架構(gòu)如圖七所示。      
                 

5 可以參考的測試項(xiàng)目:

Junit 包中有比較簡單的測試用例的例子。
Eclipse 開發(fā)平臺(tái)的 JUnit Plugin Tests and Automated Testing Framework 插件中的JunitTest項(xiàng)目例子,比較詳細(xì)的介紹了junit測試平臺(tái)。
參考文獻(xiàn)
1. JUnit官方網(wǎng)站http://www./index.htm
2. Cactus官方網(wǎng)站http://jakarta./cactus/index.html
3. Strutstestcase網(wǎng)站http://strutstestcase./
4. HttpUnit 網(wǎng)站 http:///projects/httpunit/
5. Eclipse 網(wǎng)站 http://www./downloads/index.php

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多