想飛就別怕摔

          大爺的并TM罵人

          Junit 入門實例

          JUnit 4是JUnit框架有史以來的最大改進,其主要目標便是利用Java 5的Annotation特性簡化測試用例的編寫。讓我們看看如何使用JUnit 4來進行Unit測試。

          我們使用的開發環境是Eclipse 3.2,它已經自帶了JUnit 4.1,你需要將JUnit 4 Library添加到項目用到的Library中。另外,必須使用JDK 5.0或更高版本。

          要在Eclipse環境之外運行JUnit,需要下載JUnit 4.1。

          我們先看一個簡單的Math類:

          package com.javaeedev.junit4;
          public class
           Math {

              
          public int abs(int
           value) {
                  
          return value>=0 ? value : (-
          value);
              }

              
          public int div(int a, int
           b) {
                  
          return a /
           b;
              }

              
          /**

               * BUG: if b less than 0!
               
          */
              
          public float exp(int a, int b) {
                  
          float r = 1
          ;
                  
          for(int i=0; i<b; i++
          )
                      r 
          = r *
           a;
                  
          return
           r;
              }
          }

          注意exp()方法是有Bug的,如果傳入參數2, -1,則期待的返回值應為0.5F,但實際返回值為1.0F。

          下面我們看看傳統的JUnit的TestCase:

          public class MathTest extends TestCase {

              
          public void setUp() { super
          .setUp(); }
              
          public void tearDown() { super
          .tearDown(); }

              
          public void testAbs() { assertTrue(true
          ); }
              
          public void
           testDiv() {...}
              
          public void
           testExp() {...}

          }

          JUnit依賴反射來執行每個以test開頭的方法。然而,在最新的JUnit 4中,由于有了Annotation的支持,我們的測試方法不需要再以testXxx標識了,而是寫上一個@Test標注即可。例如:

          @Test public void doAbs() {...}

          甚至MathTest類也不必繼承自TestCase。你也許會想到,不繼承自TestCase就無法調用assertXxx方法了,正因為如此,所有的assertXxx方法全部以靜態方法被放入了Assert類,使用Assert.assertXxx()調用。如果使用

          import static org.junit.Assert.*;

          則原有的代碼不必改動。

          setUp()和tearDown()方法也依賴@Before和@After標記,這樣做的最大的好處是在繼承體系內不必擔心忘記了在setUp()方法中調用父類的super.setUp()方法,JUnit框架會自動處理父類的@Before和@After標記的方法。

          并且,JUnit框架對@Before和@After的調用順序類似于類的構造方法和析構方法,即@Before按照父類到子類的順序調用,@After則相反,這樣保證了資源的正確獲取和釋放。

          當然,不再強迫必須使用setUp和tearDown作為方法名,可以使用更有意義的方法名,例如:initDatabase()和closeDatabase(),只要它們被標注了@Before和@After即可。

          來看看使用Annotation的MathTest:

          package com.javaeedev.junit4;

          import static org.junit.Assert.*
          ;

          import org.junit.*
          ;

          public class
           MathTest {

              
          public
           MathTest() {
                  System.out.println(
          "new MathTest instance."
          );
              }

              @Before
              
          public void setUp() throws
           Exception {
                  System.out.println(
          "call @Before before a test method"
          );
              }

              @After
              
          public void tearDown() throws
           Exception {
                  System.out.println(
          "call @After after a test method"
          );
              }

              @Test
              
          public void
           doAbs() {
                  Math math 
          = new
           Math();
                  assertEquals(
          200, math.abs(200
          ));
                  assertEquals(
          100, math.abs(-100
          ));
                  assertEquals(
          0, math.abs(0
          ));
              }

              @Test
              
          public void
           doDiv() {
                  Math math 
          = new
           Math();
                  assertEquals(
          5, math.div(10020
          ));
                  assertEquals(
          4, math.div(10021
          ));
              }

              @Test(expected
          =ArithmeticException.class
          )
              
          public void
           doDiv0() {
                  
          new Math().div(1270
          );
              }

              @Test(timeout
          =1
          )
              
          public void
           doLongTimeTask() {
                  
          double d = 0
          ;
                  
          for(int i=1; i<10000000; i++
          )
                      d
          +=
          i;
              }

              @Test
              
          public void
           testExp() {
                  Math math 
          = new
           Math();
                  assertEquals(32f, math.exp(
          25), 0.001f
          );
                  assertEquals(1f, math.exp(
          20), 0.001f
          );
                  assertEquals(
          0.5f, math.exp(2, (-1)), 0.001f
          );
              }

          }

          對測試異常,JUnit 4可以用expected=Exception.class來期待一個預期的異常,而不必編寫

          try {
            ...
            fail(
          "No exception"
          );
          }
          catch
          (Exception e) {
            
          // OK!

          }

          來看看doDiv0測試,我們期待一個除數為0的ArithmeticException,因此編寫如下測試方法:

          @Test(expected=ArithmeticException.class)
          public void
           doDiv0() {
              
          new Math().div(1270
          );
          }

          對于非常耗時的測試,@Test還有一個timeout來標識該方法最長執行時間,超過此時間即表示該測試方法失敗:

          @Test(timeout=1)
          public void
           doLongTimeTask() {
              
          double d = 0
          ;
              
          for(int i=1; i<10000000; i++
          )
                  d
          +=
          i;
          }

          以上方法若執行時間超過1ms則測試失敗,由于依賴CPU的執行速度,在不同的機器上測試結果也不同。

          JUnit 4另一個較大的變化是引入了@BeforeClass和@AfterClass,它們在一個Test類的所有測試方法執行前后各執行一次。這是為了能在@BeforeClass中初始化一些昂貴的資源,例如數據庫連接,然后執行所有的測試方法,最后在@AfterClass中釋放資源。

          正如你能想到的,由于@BeforeClass和@AfterClass僅執行一次,因此它們只能標記靜態方法,在所有測試方法中共享的資源也必須是靜態引用:

          private static Object dbConnection;

          @BeforeClass
          public static void setUpBeforeClass() throws
           Exception {
              System.out.println(
          "call @BeforeClass and init database connection"
          );
              dbConnection 
          = new
           Object();
          }

          @AfterClass
          public static void tearDownAfterClass() throws
           Exception {
              System.out.println(
          "call @AfterClass to release database connection"
          );
              dbConnection 
          = null
          ;
          }

          最后執行測試用例,可以看到結果:

          各個方法執行順序如下:

          call @BeforeClass and init database connection

          new MathTest instance.
          call @Before before a test method
          call @After after a test method

          new MathTest instance.
          call @Before before a test method
          call @After after a test method

          ...

          call @AfterClass to release database connection

          可以看到,@BeforeClass是在實例化MathTest之前調用的,因此不能在構造方法中初始化共享資源。

          最后需要注意的是由于Java 5的自動Box/Unbox特性,在調用assertEquals()時要特別注意,如果你傳入:

          assertEquals(100F, 100);

          則按照自動Box變為:

          assertEquals(new Float(100F), new Integer(100));

          測試失敗,因為Float類和Integer類不是同一類型。

          因此要特別注意float和double的測試。事實上對float和double應使用

          assertEquals(float, float, float delta);
          assertEquals(double, double, double delta);

          delta指定了兩個作比較的浮點數的相差范圍,在此范圍內的兩個浮點數將認為相等。可以傳入一個很小的數例如0.0001F。 

          JUnit 4非常適合使用Java 5的開發人員,但是無法在Java 1.4中獲得這些好處,并且,也不與以前的版本兼容。因此,如果你正在使用Java 5,就可以考慮使用JUnit 4來編寫測試。

          此文章來自:http://www.javaeedev.com/blog/article.jspx?articleId=ff80808112e766ee011312f144520061

          posted on 2008-11-25 00:25 生命的綻放 閱讀(4643) 評論(0)  編輯  收藏 所屬分類: JUnit


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


          網站導航:
           
          <2008年11月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          導航

          統計

          常用鏈接

          留言簿(5)

          隨筆分類(94)

          隨筆檔案(93)

          文章分類(5)

          文章檔案(5)

          相冊

          JAVA之橋

          SQL之音

          兄弟之窗

          常用工具下載

          積分與排名

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 罗甸县| 丹凤县| 鹤壁市| 双牌县| 昆明市| 濮阳县| 昌平区| 绥江县| 定结县| 应用必备| 时尚| 彭阳县| 留坝县| 阳西县| 巴东县| 腾冲县| 谷城县| 邵武市| 万安县| 徐水县| 达孜县| 建始县| 延庆县| 揭西县| 柏乡县| 临高县| 左权县| 雷波县| 锡林浩特市| 潜江市| 沽源县| 揭阳市| 久治县| 万全县| 扶沟县| 大悟县| 英山县| 信宜市| 陆川县| 会同县| 禹城市|