您的位置:軟件測(cè)試 > 開源軟件測(cè)試 > 開源單元測(cè)試工具 > junit
單元測(cè)試?yán)鱆Unit
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/3/29 14:59:08 ] 推薦標(biāo)簽:

    可是,這種 Fixture 設(shè)置方式還是引來(lái)了批評(píng),因?yàn)樗实拖,特別是在設(shè)置 Fixture 非常耗時(shí)的情況下(例如設(shè)置數(shù)據(jù)庫(kù)鏈接)。而且對(duì)于不會(huì)發(fā)生變化的測(cè)試環(huán)境或者測(cè)試數(shù)據(jù)來(lái)說(shuō),是不會(huì)影響到測(cè)試方法的執(zhí)行結(jié)果的,也沒有必要針對(duì)每一個(gè)測(cè)試方法重新設(shè)置一次 Fixture。因此在 JUnit 4 中引入了類級(jí)別的 Fixture 設(shè)置方法,編寫規(guī)范如下:

    使用注解 org,junit.BeforeClass 修飾用于初始化 Fixture 的方法。
    使用注解 org.junit.AfterClass 修飾用于注銷 Fixture 的方法。
    保證這兩種方法都使用 public static void 修飾,而且不能帶有任何參數(shù)。
類級(jí)別的 Fixture 僅會(huì)在測(cè)試類中所有測(cè)試方法執(zhí)行之前執(zhí)行初始化,并在全部測(cè)試方法測(cè)試完畢之后執(zhí)行注銷方法(圖6)。代碼范本如下:

引用
//類級(jí)別Fixture初始化方法
@BeforeClass public static void dbInit(){……}

//類級(jí)別Fixture注銷方法
@AfterClass public static void dbClose(){……}

圖6 類級(jí)別 Fixture 執(zhí)行示意圖

  異常以及時(shí)間測(cè)試

    注解 org.junit.Test 中有兩個(gè)非常有用的參數(shù):expected 和 timeout。參數(shù) expected 代表測(cè)試方法期望拋出指定的異常,如果運(yùn)行測(cè)試并沒有拋出這個(gè)異常,則 JUnit 會(huì)認(rèn)為這個(gè)測(cè)試沒有通過(guò)。這為驗(yàn)證被測(cè)試方法在錯(cuò)誤的情況下是否會(huì)拋出預(yù)定的異常提供了便利。舉例來(lái)說(shuō),方法 supportDBChecker 用于檢查用戶使用的數(shù)據(jù)庫(kù)版本是否在系統(tǒng)的支持的范圍之內(nèi),如果用戶使用了不被支持的數(shù)據(jù)庫(kù)版本,則會(huì)拋出運(yùn)行時(shí)異常 UnsupportedDBVersionException。測(cè)試方法 supportDBChecker 在數(shù)據(jù)庫(kù)版本不支持時(shí)是否會(huì)拋出指定異常的單元測(cè)試方法大體如下:

Java代碼 復(fù)制代碼

    @Test(expected=UnsupportedDBVersionException.class)  
        public void unsupportedDBCheck(){  
            ……  
    } 

    注解 org.junit.Test 的另一個(gè)參數(shù) timeout,指定被測(cè)試方法被允許運(yùn)行的長(zhǎng)時(shí)間應(yīng)該是多少,如果測(cè)試方法運(yùn)行時(shí)間超過(guò)了指定的毫秒數(shù),則JUnit認(rèn)為測(cè)試失敗。這個(gè)參數(shù)對(duì)于性能測(cè)試有一定的幫助。例如,如果解析一份自定義的 XML 文檔花費(fèi)了多于 1 秒的時(shí)間,需要重新考慮 XML 結(jié)構(gòu)的設(shè)計(jì),那單元測(cè)試方法可以這樣來(lái)寫:

Java代碼 復(fù)制代碼

    @Test(timeout=1000)  
        public void selfXMLReader(){  
            ……  
    } 

  忽略測(cè)試方法

    JUnit 提供注解 org.junit.Ignore 用于暫時(shí)忽略某個(gè)測(cè)試方法,因?yàn)橛袝r(shí)候由于測(cè)試環(huán)境受限,并不能保證每一個(gè)測(cè)試方法都能正確運(yùn)行。例如下面的代碼便表示由于沒有了數(shù)據(jù)庫(kù)鏈接,提示 JUnit 忽略測(cè)試方法 unsupportedDBCheck:

Java代碼 復(fù)制代碼

    @ Ignore(“db is down”)  
    @Test(expected=UnsupportedDBVersionException.class)  
        public void unsupportedDBCheck(){  
            ……  
    } 

    但是一定要小心。注解 org.junit.Ignore 只能用于暫時(shí)的忽略測(cè)試,如果需要永遠(yuǎn)忽略這些測(cè)試,一定要確認(rèn)被測(cè)試代碼不再需要這些測(cè)試方法,以免忽略必要的測(cè)試點(diǎn)。

測(cè)試運(yùn)行器

    又一個(gè)新概念出現(xiàn)了——測(cè)試運(yùn)行器,JUnit 中所有的測(cè)試方法都是由它負(fù)責(zé)執(zhí)行的。JUnit 為單元測(cè)試提供了默認(rèn)的測(cè)試運(yùn)行器,但 JUnit 并沒有限制您必須使用默認(rèn)的運(yùn)行器。相反,您不僅可以定制自己的運(yùn)行器(所有的運(yùn)行器都繼承自 org.junit.runner.Runner),而且還可以為每一個(gè)測(cè)試類指定使用某個(gè)具體的運(yùn)行器。指定方法也很簡(jiǎn)單,使用注解 org.junit.runner.RunWith 在測(cè)試類上顯式的聲明要使用的運(yùn)行器即可:

Java代碼 復(fù)制代碼

    @RunWith(CustomTestRunner.class)  
    public class TestWordDealUtil {  
    ……  
    } 

  顯而易見,如果測(cè)試類沒有顯式的聲明使用哪一個(gè)測(cè)試運(yùn)行器,JUnit 會(huì)啟動(dòng)默認(rèn)的測(cè)試運(yùn)行器執(zhí)行測(cè)試類(比如上面提及的單元測(cè)試代碼)。一般情況下,默認(rèn)測(cè)試運(yùn)行器可以應(yīng)對(duì)絕大多數(shù)的單元測(cè)試要求;當(dāng)使用 JUnit 提供的一些高級(jí)特性(例如即將介紹的兩個(gè)特性)或者針對(duì)特殊需求定制 JUnit 測(cè)試方式時(shí),顯式的聲明測(cè)試運(yùn)行器必不可少了。

測(cè)試套件

  在實(shí)際項(xiàng)目中,隨著項(xiàng)目進(jìn)度的開展,單元測(cè)試類會(huì)越來(lái)越多,可是直到現(xiàn)在我們還只會(huì)一個(gè)一個(gè)的單獨(dú)運(yùn)行測(cè)試類,這在實(shí)際項(xiàng)目實(shí)踐中肯定是不可行的。為了解決這個(gè)問(wèn)題,JUnit 提供了一種批量運(yùn)行測(cè)試類的方法,叫做測(cè)試套件。這樣,每次需要驗(yàn)證系統(tǒng)功能正確性時(shí),只執(zhí)行一個(gè)或幾個(gè)測(cè)試套件便可以了。測(cè)試套件的寫法非常簡(jiǎn)單,您只需要遵循以下規(guī)則:

創(chuàng)建一個(gè)空類作為測(cè)試套件的入口。
    使用注解 org.junit.runner.RunWith 和org.junit.runners.Suite.SuiteClasses 修飾這個(gè)空類。
將 org.junit.runners.Suite 作為參數(shù)傳入注解 RunWith,以提示 JUnit 為此類使用套件運(yùn)行器執(zhí)行。
    將需要放入此測(cè)試套件的測(cè)試類組成數(shù)組作為注解 SuiteClasses 的參數(shù)。
    保證這個(gè)空類使用 public 修飾,而且存在公開的不帶有任何參數(shù)的構(gòu)造函數(shù)。
Java代碼 復(fù)制代碼

    package com.ai92.cooljunit;  
     
    import org.junit.runner.RunWith;  
    import org.junit.runners.Suite;  
    ……  
     
    /** 
     * 批量測(cè)試 工具包 中測(cè)試類 
     * @author Ai92 
     */ 
    @RunWith(Suite.class)  
    @Suite.SuiteClasses({TestWordDealUtil.class})  
    public class RunAllUtilTestsSuite {  
    } 

    上例代碼中,我們將前文提到的測(cè)試類 TestWordDealUtil 放入了測(cè)試套件 RunAllUtilTestsSuite 中,在 Eclipse 中運(yùn)行測(cè)試套件,可以看到測(cè)試類 TestWordDealUtil 被調(diào)用執(zhí)行了。測(cè)試套件中不僅可以包含基本的測(cè)試類,而且可以包含其它的測(cè)試套件,這樣可以很方便的分層管理不同模塊的單元測(cè)試代碼。但是,您一定要保證測(cè)試套件之間沒有循環(huán)包含關(guān)系,否則無(wú)盡的循環(huán)會(huì)出現(xiàn)在您的面前……。

參數(shù)化測(cè)試

    回顧一下我們?cè)谛」?jié)“JUnit 初體驗(yàn)”中舉的實(shí)例。為了保證單元測(cè)試的嚴(yán)謹(jǐn)性,我們模擬了不同類型的字符串來(lái)測(cè)試方法的處理能力,為此我們編寫大量的單元測(cè)試方法?墒沁@些測(cè)試方法都是大同小異:代碼結(jié)構(gòu)都是相同的,不同的僅僅是測(cè)試數(shù)據(jù)和期望值。有沒有更好的方法將測(cè)試方法中相同的代碼結(jié)構(gòu)提取出來(lái),提高代碼的重用度,減少?gòu)?fù)制粘貼代碼的煩惱?在以前的 JUnit 版本上,并沒有好的解決方法,而現(xiàn)在您可以使用 JUnit 提供的參數(shù)化測(cè)試方式應(yīng)對(duì)這個(gè)問(wèn)題。

上一頁(yè)123456下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd