posts - 22, comments - 32, trackbacks - 0, articles - 73
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          前言:JUnit元數(shù)據(jù)

          @Before: 
          使用了該元數(shù)據(jù)的方法在每個(gè)測(cè)試方法執(zhí)行之前都要執(zhí)行一次。 
          @After: 
          使用了該元數(shù)據(jù)的方法在每個(gè)測(cè)試方法執(zhí)行之后要執(zhí)行一次。 
          注意:@Before和@After標(biāo)示的方法只能各有一個(gè)。這個(gè)相當(dāng)于取代了JUnit以前版本中的setUp和tearDown方法,當(dāng)然你還可以繼續(xù)叫這個(gè)名字,不過(guò)JUnit不會(huì)霸道的要求你這么做了。
          @Test(expected=*.class) 
          在JUnit4.0之前,對(duì)錯(cuò)誤的測(cè)試,我們只能通過(guò)fail來(lái)產(chǎn)生一個(gè)錯(cuò)誤,并在try塊里面assertTrue(true)來(lái)測(cè)試。現(xiàn)在,通過(guò)@Test元數(shù)據(jù)中的expected屬性。expected屬性的值是一個(gè)異常的類型
          @Test(timeout=xxx): 
          該元數(shù)據(jù)傳入了一個(gè)時(shí)間(毫秒)給測(cè)試方法, 
          如果測(cè)試方法在制定的時(shí)間之內(nèi)沒有運(yùn)行完,則測(cè)試也失敗。 
          @ignore: 
          該元數(shù)據(jù)標(biāo)記的測(cè)試方法在測(cè)試中會(huì)被忽略。當(dāng)測(cè)試的方法還沒有實(shí)現(xiàn),或者測(cè)試的方法已經(jīng)過(guò)時(shí),或者在某種條件下才能測(cè)試該方法(比如需要一個(gè)數(shù)據(jù)庫(kù)聯(lián)接,而在本地測(cè)試的時(shí)候,數(shù)據(jù)庫(kù)并沒有連接),那么使用該標(biāo)簽來(lái)標(biāo)示這個(gè)方法。同時(shí),你可以為該標(biāo)簽傳遞一個(gè)String的參數(shù),來(lái)表明為什么會(huì)忽略這個(gè)測(cè)試方 法。比如:@lgnore(“該方法還沒有實(shí)現(xiàn)”),在執(zhí)行的時(shí)候,僅會(huì)報(bào)告該方法沒有實(shí)現(xiàn),而不會(huì)運(yùn)行測(cè)試方法。、

          一、包含必要地Package

          最主要地一個(gè) Package就是org.junit.*,把它包含進(jìn)來(lái)之后,絕大部分功能就有了。還有一句話也非常地重要“import static org.junit.Assert.*;”,我們?cè)跍y(cè)試的時(shí)候使用的一系列assertEquals方法就來(lái)自這個(gè)包。大家注意一下,這是一個(gè)靜態(tài)包含 (static),是JDK5中新增添的一個(gè)功能。也就是說(shuō),assertEquals是Assert類中的一系列的靜態(tài)方法

          二、測(cè)試類的聲明

          測(cè)試類是一個(gè)獨(dú)立的類,沒有任何父類。測(cè)試類的名字也可以任意命名,沒有任何局限性。它與普通類的區(qū)別在于它內(nèi)部的方法的聲明

          三、創(chuàng)建一個(gè)待測(cè)試的對(duì)象

          你要測(cè)試哪個(gè)類,那么你首先就要?jiǎng)?chuàng)建一個(gè)該類的對(duì)象。

          private staticCalculator calculator =newCalculator();

          為了測(cè)試Calculator類,我們必須創(chuàng)建一個(gè)calculator對(duì)象。

          四、測(cè)試方法的聲明

          在測(cè)試類中,并不是每一個(gè)方法都是用于測(cè)試的,你必須使用“標(biāo)注”來(lái)明確表明哪些是測(cè)試方法。“標(biāo)注”也是JDK5的一個(gè)新特性,用在此處非常恰當(dāng)。我們可以看到,在某些方法的前有@Before、@Test、@Ignore等字樣,這些就是標(biāo)注,以一個(gè)“@”作為開頭。這些標(biāo)注都是JUnit4自定義 的,熟練掌握這些標(biāo)注的含義非常重要。

          六、 忽略測(cè)試某些尚未完成的方法

          七、 Fixture(暫且翻譯為“固定代碼段”)

          Fixture 的含義就是“在某些階段必然被調(diào)用的代碼”。“在任何一個(gè)測(cè)試執(zhí)行之前必須執(zhí)行的代碼”就是一個(gè)Fixture,我們用@Before來(lái)標(biāo)注它

          一、 高級(jí)Fixture

          兩個(gè)Fixture標(biāo)注,分別是@Before和@After,是否適合完成如下功能:有一個(gè)類是負(fù)責(zé)對(duì)大文件(超過(guò) 500兆)進(jìn)行讀寫,他的每一個(gè)方法都是對(duì)文件進(jìn)行操作。換句話說(shuō),在調(diào)用每一個(gè)方法之前,我們都要打開一個(gè)大文件并讀入文件內(nèi)容,這絕對(duì)是一個(gè)非常耗費(fèi)時(shí)間的操作。如果我們使用@Before和@After,那么每次測(cè)試都要讀取一次文件,效率及其低下。這里我們所希望的是在所有測(cè)試一開始讀一次文件, 所有測(cè)試結(jié)束之后釋放文件,而不是每次測(cè)試都讀文件。JUnit的作者顯然也考慮到了這個(gè)問題,它給出了@BeforeClass 和 @AfterClass兩個(gè)Fixture來(lái)幫我們實(shí)現(xiàn)這個(gè)功能。從名字上就可以看出,用這兩個(gè)Fixture標(biāo)注的函數(shù),只在測(cè)試用例初始化時(shí)執(zhí)行@BeforeClass方法,當(dāng)所有測(cè)試執(zhí)行完畢之后,執(zhí)行@AfterClass進(jìn)行收尾工作。在這里要注意一下,每個(gè)測(cè)試類只能有一個(gè)方法被標(biāo)注為 @BeforeClass或@AfterClass,并且該方法必須是Public和Static的。

          二、 限時(shí)測(cè)試

          那個(gè)求平方根的函數(shù)有Bug,是個(gè)死循環(huán):

            public voidsquareRoot(intn) ...{

                   for(; ;) ;//Bug : 死循環(huán)

            }

          如果測(cè)試的時(shí)候遇到死循環(huán),對(duì)于那些邏輯很復(fù)雜,循環(huán)嵌套比較深的程序,很有可能出現(xiàn)死循環(huán),因此一定要采取一些預(yù)防措施。我們給這些測(cè)試函數(shù)設(shè)定一個(gè)執(zhí)行時(shí)間,超過(guò)了這個(gè)時(shí)間,他們就會(huì)被系統(tǒng)強(qiáng)行終止,并且系統(tǒng)還會(huì)向你匯報(bào)該函數(shù)結(jié)束的原因是因?yàn)槌瑫r(shí),這樣你就可以發(fā)現(xiàn)這些Bug了。只需要給@Test標(biāo)注加一個(gè)參數(shù)即可,代碼如下:

            @Test(timeout = 1000)

            public voidsquareRoot() ...{

                   calculator.squareRoot(4);

                   assertEquals(2,calculator.getResult());

            }

            Timeout參數(shù)表明了你要設(shè)定的時(shí)間,單位為毫秒,因此1000就代表1秒。

          三、 測(cè)試異常

          經(jīng)常會(huì)編寫一些需要拋出異常的函數(shù),如果一個(gè)函數(shù)應(yīng)該拋出異常,但是它沒拋出,當(dāng)然是Bug。例如,我們寫的計(jì)算器類有除法功能,如果除數(shù)是一個(gè)0,那么必然要拋出“除0異常”。因此,我們很有必要對(duì)這些進(jìn)行測(cè)試。代碼如下:

            @Test(expected = ArithmeticException.class)

            public void divideByZero() ...{

                   calculator.divide(0);

            }

          如上述代碼所示,我們需要使用@Test標(biāo)注的expected屬性,將我們要檢驗(yàn)的異常傳遞給他,這樣JUnit框架就能自動(dòng)幫我們檢測(cè)是否拋出了我們指定的異常。

          四、 Runner (運(yùn)行器)

          把測(cè)試代碼提交給JUnit框架后,框架如何來(lái)運(yùn)行代碼呢?答案就是——Runner。在JUnit中有很多個(gè) Runner,他們負(fù)責(zé)調(diào)用測(cè)試代碼,每一個(gè)Runner都有各自的特殊功能,要根據(jù)需要選擇不同的Runner來(lái)運(yùn)行測(cè)試代碼。JUnit中有一個(gè)默認(rèn)Runner,如果沒有指定,那么系統(tǒng)自動(dòng)使用默認(rèn) Runner來(lái)運(yùn)行你的代碼。換句話說(shuō),下面兩段代碼含義是完全一樣的:

          import org.junit.runner.RunWith;

          import org.junit.runners.Suite;

           

          @RunWith(Suite.class)

          @Suite.SuiteClasses({

          MyTestCase.class, //測(cè)試類

          PartSuite.class, //另一個(gè)測(cè)試套

          })

          public class AllTestCases {

          }

            要想指定一個(gè)Runner,需要使用@RunWith標(biāo)注,并且把你所指定的Runner作為參數(shù)傳遞給它。另外一個(gè)要注意的 是,@RunWith是用來(lái)修飾類的,而不是用來(lái)修飾函數(shù)的。只要對(duì)一個(gè)類指定了Runner,那么這個(gè)類中的所有函數(shù)都被這個(gè)Runner來(lái)調(diào)用。

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

          一個(gè)對(duì)考試分?jǐn)?shù)進(jìn)行評(píng)價(jià)的函數(shù),返回值分別為“優(yōu)秀,良好,一般,及格,不及格”,因此你在編寫測(cè)試的時(shí)候,至少要寫5個(gè)測(cè)試,把這5中情況都包含了,這 確實(shí)是一件很麻煩的事情。我們還使用我們先前的例子,測(cè)試一下“計(jì)算一個(gè)數(shù)的平方”這個(gè)函數(shù),暫且分三類:正數(shù)、0、負(fù)數(shù)。測(cè)試代碼如下:

          importorg.junit.AfterClass;

            importorg.junit.Before;

            importorg.junit.BeforeClass;

            importorg.junit.Test;

            importstatic org.junit.Assert.*;

            public classAdvancedTest ...{

                   private static Calculator calculator =new Calculator();

                   @Before

                   public void clearCalculator() ...{

                          calculator.clear();

                   }

                   @Test

                   public void square1() ...{

                          calculator.square(2);

                          assertEquals(4,calculator.getResult());

                   }

                   @Test

                   public void square2() ...{

                   calculator.square(0);

                   assertEquals(0, calculator.getResult());

                   }

                   @Test

                   public void square3() ...{

                          calculator.square(-3);

                          assertEquals(9,calculator.getResult());

                   }

          }

          為了簡(jiǎn)化類似的測(cè)試,JUnit4提出了“參數(shù)化測(cè)試”的概念,只寫一個(gè)測(cè)試函數(shù),把這若干種情況作為參數(shù)傳遞進(jìn)去,一次性的完成測(cè)試。代碼如下:

            importstatic org.junit.Assert.assertEquals;

            importorg.junit.Test;

            importorg.junit.runner.RunWith;

            importorg.junit.runners.Parameterized;

            importorg.junit.runners.Parameterized.Parameters;

            importjava.util.Arrays;

            importjava.util.Collection;

            @RunWith(Parameterized.class)

            public classSquareTest{

            private static Calculator calculator = new Calculator();

                   private int param;

                   private int result;

                   @Parameters

                   public static Collection data(){

                          return Arrays.asList(newObject[][]...{

                          {2, 4},

                          {0, 0},

                          {-3, 9},

                   });

            }

          //構(gòu)造函數(shù),對(duì)變量進(jìn)行初始化

          六、斷言和假設(shè)

          斷言:org.junit.Assert用于測(cè)試用例中,如果斷言失敗,用例即結(jié)束。

          假設(shè):org.junit.Assume用于在準(zhǔn)備環(huán)境時(shí)判斷環(huán)境是否符合要求,包括測(cè)試套的@BeforeClass,測(cè)試類的@BeforeClass,測(cè)試類的實(shí)例化,測(cè)試類的@Before。

          如果假設(shè)失敗,假設(shè)所處初始化代碼方法立即結(jié)束,更深級(jí)別的后續(xù)工作也被忽略,相關(guān)測(cè)試用例被忽略,但與假設(shè)同級(jí)別的收尾工作還要繼續(xù)執(zhí)行。 
          例如:如果在測(cè)試類的@BeforeClass中假設(shè)失敗,該類的實(shí)例化及子級(jí)別將被忽略,@AfterClass會(huì)繼續(xù)執(zhí)行。
          七、工程實(shí)例
               
           如果不想在單元測(cè)試中操作數(shù)據(jù)庫(kù)中的數(shù)據(jù)。可以在測(cè)試方法上加 
               @Test

              @Transactional //單元測(cè)試  @Transactional 不會(huì)進(jìn)行數(shù)據(jù)提交事物
              @Rollback(true) // 這個(gè)注釋可以不用加(單元測(cè)試默認(rèn)值)
              public void testaddUserPrivate()throws Exception{
                  UserPrivate userPrivate=new UserPrivate();
                  userPrivate.setTenantId("31");
                  userPrivate.setMenuCode("7777888");
                  userPrivate.setpUid("111222");
                  userPrivate.setRoleId("3332277");
                  userPrivate.setValue("99999");
                  userPrivate.setUpdateDateTime(new Date());
                  userPrivate.setCreateDateTime(new Date());
                  int s=userPrivateService.addUserPrivate(userPrivate);
                  Assert.assertEquals(1, s); // 這是斷言的使用
              }
                  

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 会宁县| 泰和县| 高安市| 连州市| 庄河市| 娱乐| 舟山市| 民勤县| 翁牛特旗| 和平县| 兴仁县| 疏附县| 宝山区| 扎鲁特旗| 招远市| 蒙阴县| 广水市| 尉氏县| 蛟河市| 贵溪市| 三门县| 沿河| 赤城县| 陇川县| 察隅县| 星子县| 城市| 长垣县| 宁都县| 安塞县| 瑞金市| 玉林市| 阜城县| 德昌县| 肃南| 隆化县| 北票市| 孟州市| 焦作市| 紫金县| 儋州市|