<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    lexy

    支持開源,尊重他人的勞動!

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      17 隨筆 :: 0 文章 :: 9 評論 :: 0 Trackbacks

    JUnit使用經驗 <轉載>
                                          
    原作:Andy Schneider Richard Dallaway 等
     編譯:PMT 測試工作組
     --------------------------------------------------------------------------------

     譯者注:
         很多測試人員都有過編寫測試框架的經歷,JUnit的出現避免了其中的大量重復勞動。但如同其他的工具一樣用得好和用得差的結果是截然不同的。我們編輯這樣一個JUnit的系列希望能夠幫助越來越多的JUnit使用者用好JUnit。我們也希望讀者們能夠把自己的一些經驗所得和大家分享。

     經驗一、不要在測試用例的構造函數中做初始化
         答案是重載測試用例的setUp()方法進行初始化。

     經驗二、不要假定測試用例中測試的執行次序
         好的習慣是保持測試之間的獨立性,使得它們在任何次序下執行的結果都是相同的。

     經驗三、測試要避免人工干預
         經驗二講的是不同的測試要避免相關性,而經驗三講的其實就是測試要避免自相關。

     經驗四、在子類中調用父類的setUp() 和tearDown()

     經驗五、不要硬性規定數據文件的路徑

     經驗六、把測試的代碼和被測的代碼放在同樣的目錄下

     經驗七、正確命名測試

     經驗八、書寫測試時要考慮地區和國家設置

     經驗九、利用Junit 的自動異常處理書寫簡潔的測試代碼
         事實上在Junit 中使用try-catch 來捕獲異常是沒有必要的,Junit 會自動捕獲異常。那些沒有被捕獲的異常就被當成錯誤處理。

     經驗十、充分利用Junit 的assert/fail 方法
         assertSame()用來測試兩個引用是否指向同一個對象
         assertEquals()用來測試兩個對象是否相等

     經驗十一、確保測試代碼與時間無關

     經驗十二、使用文檔生成器做測試文檔

     

    經驗一、不要在測試用例的構造函數中做初始化
    當我們需要增加一個測試時,我們要書寫一個自己的測試用例,比如SomeTest。如果你喜歡在SomeTest的
    構造函數中做有關的初始化工作,這可不是個好習慣。如下例:


    public Class SomeTestclass SomeTest extends TestCase{
        public SomeTest(String testName){
            super(testName);
            //初始化代碼
        }
    }
    一旦初始化代碼產生異常,比如IllegalStateException,JUnit隨之將產生一個AssertionFailedError,
    并顯示類似下面的出錯信息:
    junit.framework.AssertionFailedError:Cannotinstantiatetestcase:test1at
    junit.framework.Assert.fail(Assert.java:143at
    junit.framework.TestSuite$1.runTest(TestSuite.java:178at
    junit.framework.TestCase.runBare(TestCase.java:129at
    junit.framework.TestResult$1.protect(TestResult.java:100at
    junit.framework.TestResult.runProtected(TestResult.java:117at
    junit.framework.TestResult.run(TestResult.java:103at
    junit.framework.TestCase.run(TestCase.java:120at
    junit.framework.TestSuite.run(TestSuite.java,CompiledCodeat
    junit.ui.TestRunner$12.run(TestRunner.java:429
    這一大堆出錯信息只會讓人一頭霧水,我們只知道JUnit無法實例化某個測試用例,到底出了什么問題,在
    哪兒出錯了呢?不知道!
    那么好的做法是怎樣呢?
    答案是重載測試用例的setUp()方法進行初始化。當setUp()中的初始化代碼產生異常時我們得到的
    是類似下面的出錯信息:
    java.lang.IllegalStateException:Oopsatbp.DTC.setUp(DTC.java:34at
    junit.framework.TestCase.runBare(TestCase.java:127at
    junit.framework.TestResult$1.protect(TestResult.java:100at
    junit.framework.TestResult.runProtected(TestResult.java:117at
    junit.framework.TestResult.run(TestResult.java:103
    ...
    顯然這要清楚得多我們一下子就可以知道是在DTC.java 的第34 行產生了IllegalStateException

     

    經驗二、不要假定測試用例中測試的執行次序
    我們知道在一個JUnit 的測試用例類中可以包含多個測試,每個測試其實就是一個method。在下面的例子
    中有兩個不同的測試,盡管testDoThisFirst()在位置上先于testDoThisSecond(),但我們不能就此假定
    testDoThisFirst()會先執行。


    public Class SomeTestCaseclass SomeTestCase extends TestCase{
        public SomeTestCase(String testName){
            super(testName);
        }
        public void testDoThisFirst(){
           
        }
        public void testDoThisSecond(){
        }
    }由于JUnit 內部使用一個Vector 來存儲所有的test,因此在不同的操作系統和Java 虛擬機上,test 的執行
    次序是不可預測的。
    好的習慣是保持測試之間的獨立性,使得它們在任何次序下執行的結果都是相同的。如果真得需要某些測試
    按照特定的次序執行,我們可以借助addTest 來實現。如下例:


    public static Testsuite(){
        suite.addTest(new SomeTestCase(“testDoThisFirst”);
        suite.addTest(new SomeTestCase(“testDoThisSecond”);
        return suite;
    }
    這樣我們可以確保JUnit先執行testDoThisFirst(),然后執行testDoThisSecond()。

    經驗三、測試要避免人工干預
    如果某段測試代碼需要人工干預,那至少有兩個不良后果:一則不能被包括在自動測試中,比如夜間的回
    歸測試;二則不能被重復執行,例如數據刪除的測試不能做完刪除就萬事大吉,比較好的做法是自動補上
    刪除掉的數據。經驗二講的是不同的測試要避免相關性,而經驗三講的其實就是測試要避免自相關。

    經驗四、在子類中調用父類的setUp() 和tearDown()讓我們看一看下面的代碼

    public Class SomeTestCaseclass SomeTestCase extends AnotherTestCase {
        // A connection to a database
        private Database theDatabase;
        public SomeTestCase (String testName) {
            super (testName);
        }
        public void testFeatureX () {
           
        }
        public void setUp () {
            // Clear out the database
            theDatabase.clear ();
        }
    }你發現其中的錯誤了嗎?setUp()應該調用super.setUp() 以確保AnotherTestCase 中定義的環境被初
    始化了。當然這也有例外,就是基類可以處理任意的測試數據。


     經驗五、不要硬性規定數據文件的路徑
    我們經常需要從文件系統中讀取測試數據,看下面的代碼:

    public void setUp () {
        FileInputStream inp ("C:\TestData\dataSet1.dat";
       
    }
    這段代碼需要把測試數據文件dataSet1.dat 放在C:TestData,這是有問題的。
    第一,C 盤可能沒有磁盤空間了測試人員不得不把數據文件放到其他路徑;
    第二,可能需要在其他操作系統比如Linux 上執行這一測試。
    所以,一個較好的替代方案是

    public void setUp () {
        FileInputStream inp ("dataSet1.dat";
       
    }

    但事實上這樣仍不是很好,因為這要求數據文件的路徑和測試執行的路徑必須是同一個,如果幾個不同
    的測試都這樣的話,那要把這些測試集合起來執行就有些困難,我們不得不頻繁的改變當前路徑。
    為了解決這個問題,我們可以使用Class.getResource()或者Class.getResourceAsStream(),這樣我
    們可以把數據文件放在這個Class 的某個相對路徑上。
    數據文件應該盡可能和源代碼一起都放在配置管理系統上,但這樣一來如果我們采用上面的Resource 機
    制,我們就需要做一件工作,就是把數據文件從原來的位置-就是源代碼的某個相對路徑,拷貝到編譯后
    的位置,也就是class 文件的相應的相對路徑。這其實并不復雜,因為從class 的package 就可以映射到
    java文件的所在路徑對于Linux或者Windows我們所要做的就是把package中的. 用
    File.separatorChar 替代。

     

    經驗六、把測試的代碼和被測的代碼放在同樣的目錄下
    當我們把測試代碼和被測的代碼放在同一目錄下時,我們就可以在編譯被測代碼的同時編譯測試代碼,從
    而確保兩者是同步更新的。事實上當前的普遍做法,就是把單元測試視為Build 的一個環節。

    經驗七、正確命名測試
    把測試用例命名為TestClassUnderTest,比如如果被測的Class 是MessageLog,那么測試用例就叫
    TestMessageLog,這樣做使得測試用例和被測的Class一一對應,而在測試用例中每個測試的method 就
    可以命名為
    testLoggingEmptyMessage()
    testLoggingNullMessage()
    testLoggingWarningMessage()
    testLoggingErrorMessage()
    同樣是為了說清楚測試的是什么。正確的命名可以幫助測試代碼的閱讀者了解每個測試的目的。


     
    經驗八、書寫測試時要考慮地區和國家設置
    比如某個測試要使用日期,下面的代碼就是創建日期對象的一種方法
    Date date = DateFormat.getInstance ().parse ("dd/mm/yyyy";
    但是如果運行上面測試代碼的機器采用不同的地區國家設置,那么就會有問題。因此我們最好用下面的另
    一種方法:
    Calendar cal = Calendar.getInstance ();
    Cal.set (yyyy, mm-1, dd);
    Date date = Calendar.getTime ();
    顯然,第二種方法能夠適應地區國家設置的變化。


     
    經驗九、利用Junit 的自動異常處理書寫簡潔的測試代碼
    很多Junit 的初學者經常會寫出類似下面的這些代碼


    public void exampleTest () {
        try {
            // do some test
        } catch (SomeApplicationException e) {
            fail ("Caught SomeApplicationException exception";
        }
    }
    事實上在Junit 中使用try-catch 來捕獲異常是沒有必要的,Junit 會自動捕獲異常。那些沒有被捕獲的異常就
    被當成錯誤處理。所以上面的代碼很冗余,完全可以寫成下面等效卻簡潔得多的代碼:

    public void exampleTest () throws SomeApplicationException {
        // do some test
    }
    更少的測試代碼也更容易讀懂更容易維護。

     


    經驗十、充分利用Junit 的assert/fail 方法
    Junit 有豐富而靈活的assert/fail 方法,如何用好這些方法也是大有講究的。比如下面的寫法就不大好
    assert (creds == 3);
    不如寫成
    assertEquals ("The number of credentials should be 3", 3, creds);
    第二種寫法不僅易于閱讀,而且在執行時如果fail 也可以向測試人員提供更多的信息。
    Junit 也有支持浮點數的assert方法,干凈利索如下例
    assertEquals ("some message", result, expected, delta);
    另外要一提的是:
    assertSame()用來測試兩個引用是否指向同一個對象
    assertEquals()用來測試兩個對象是否相等


    經驗十一、確保測試代碼與時間無關
    盡量避免可能過期的測試數據,這種數據應該可以手工或者自動的刷新。另外還有一個技巧就是在使用這些
    數據前更改系統的當前日期,數據操作結束后再恢復日期。當然,使用這一技巧要注意可能的副作用。

    經驗十二、使用文檔生成器做測試文檔
    我們當然可以使用文本編輯器來書寫單元測試的文檔,但是更好的方法是使用文檔生成器比如JavaDoc自
    動生成,這樣我們就不需擔心實現和文檔之間的同步問題。自動生成的文檔格式統一錯誤也少。

     

    posted on 2007-10-25 17:16 lexy 閱讀(1580) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     
    主站蜘蛛池模板: 国产精品1024在线永久免费| 免费无码午夜福利片| 日韩内射激情视频在线播放免费| 亚洲综合网站色欲色欲| 一级做a爱过程免费视| 久久久亚洲精品蜜桃臀| 国产一级婬片A视频免费观看| 亚洲国产一级在线观看| 久久久受www免费人成| 亚洲大成色www永久网站| 99久久99久久精品免费观看| 亚洲熟妇色自偷自拍另类| 精品无码人妻一区二区免费蜜桃| 亚洲精品国产成人| 成人福利免费视频| 亚洲日韩看片无码电影| 亚洲国产天堂久久久久久| 爽爽爽爽爽爽爽成人免费观看| 亚洲AV日韩精品久久久久久| 亚洲视频免费播放| 亚洲人成未满十八禁网站| 亚洲AV无码成H人在线观看| 精品一区二区三区免费视频| 亚洲午夜未满十八勿入| 97无码免费人妻超级碰碰夜夜| 国产亚洲视频在线观看| 亚洲女初尝黑人巨高清| 91九色视频无限观看免费| 亚洲6080yy久久无码产自国产| 亚洲一级Av无码毛片久久精品| 99精品视频在线视频免费观看| 亚洲午夜福利在线视频| 国产成人精品日本亚洲专区61| 18禁男女爽爽爽午夜网站免费| 亚洲aⅴ无码专区在线观看| 亚洲AV无码成人精品区在线观看| 无限动漫网在线观看免费| eeuss在线兵区免费观看| 亚洲人成免费网站| 亚洲色偷拍区另类无码专区| 无码国产精品一区二区免费式影视|