Java單元測試之JUnit4

1.JUnit4簡介

     JUnit4

     JUnit是Java實現單元測試的框架,JUnit4是利用Java5的註解來簡化測試用例的編寫。

2.JUnit3編寫單元測試示例

    2.1 測試示例類

public class AddOperation {
    public int add(int x,int y){
        return x+y;
    }
}

     2.2 測試示例類對應的單元測試

import junit.framework.TestCase;
//import關鍵字後面加上static關鍵字是使用了JDK5中的靜態導入
//這樣我們可以把後面的類中的static的變量和方法導入這個類中,
//並且可以當作自己定義的變量和方法使用
import static org.junit.Assert.*;
public class AddOperationTest extends TestCase{

    public void setUp() throws Exception {}

    public void tearDown() throws Exception {}

    public void testAdd() {
        System.out.println(\"add\");
        int x = 0;
        int y = 0;
        AddOperationinstance = new AddOperation();
        int expResult = 0;
        int result =instance.add(x, y);
        assertEquals(expResult,result);
    }
}

     2.3 JUnit3單元測試總結

          1. 單元測試類必須繼承TestCase類。

          2. 要測試的方法必須以test開頭。   

3. JUnit4 編寫單元測試示例

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

public class AddOperationTest{

    @Before
    public void setUp() throws Exception {}

    @Test
    public void add() {
        System.out.println(\"add\");
        int x = 0;
        int y = 0;
        AddOperationinstance = new AddOperation();
        int expResult = 0;
        int result =instance.add(x, y);
        assertEquals(expResult,result);
    }

    @After
    public void tearDown() throws Exception {}
}

總結:在JUnit4中我們沒必要必須繼承TestCase,而且測試的方法沒必要以test開頭,只需要使用@Test註解即可。

4. JUnit4中常用的註解含義及其使用

      @RunWith: 可以更改測試運行器,可以自己設置運行器,只需要繼承org.junit.runner.Runner這個類就行

      @Before:使用了該元數據的方法在每個測試方法執行之前都要執行一次,初始化方法。
      @After:使用了該元數據的方法在每個測試方法執行之後要執行一次,釋放方法佔用的資源。

      @BeforeClass:使用了該元數據的方法會被static關鍵字修飾,該方法會在所有的方法運行前被執行。
      @AfterClass:使用了該元數據的方法會被static關鍵字修飾,該方法會在所有的方法運行前被執行。

      注意:@Before和@After標示的方法只能各有一個。這個相當於取代了JUnit以前版本中的setUp和tearDown方法。


      @Test(expected=XXXException.class):在JUnit4.0之前,對錯誤的測試,我們只能通過fail來產生一個錯誤,並在try塊裏面assertTrue(true)來測試。現在,通過@Test元數據中的expected屬性,expected屬性的值是一個異常的類型。

異常測試示例表
測試類型 異常測試
測試適用場景 JAVA中的異常處理也是一個重點,因此你經常會編寫一些需要拋出異常的函數。那麼,如果你覺得一個函數應該拋出異常,但是它沒拋出,這算不算Bug呢?這當然是Bug,並JUnit也考慮到了這一點,來幫助我們找到這種Bug。例如,我們寫的計算器類有除法功能,如果除數是一個0,那麼必然要拋出“除0異常”。因此,我們很有必要對這些進行測試。
代碼示例

@Test(expected = ArithmeticException.class)

public void divideByZero(){

         calculator.divide(0);

}

測試結果分析 我們需要使用@Test標註的expected屬性,將我們要檢驗的異常傳遞給他,這樣JUnit框架就能自動幫我們檢測是否拋出了我們指定的異常。

       @Test(timeout=xxx):該元數據傳入了一個時間(毫秒級)給測試方法,如果測試方法在制定的時間之內沒有運行完,則測試也失敗。

限時測試示例表
測試類型 限時測試
測試適用場景 對於那些邏輯很複雜,循環嵌套比較深的程序,很有可能出現死循環,因此一定要採取一些預防措施。限時測試是一個很好的解決方案。我們給這些測試函數設定一個執行時間,超過了這個時間,他們就會被系統強行終止,並且系統還會向你彙報該函數結束的原因是因爲超時,這樣你就可以發現這些Bug了。要實現這一功能,只需要給@Test標註加一個參數即可。
代碼示例

 //Timeout參數表明了你要設定的時間,單位爲毫秒,因此1000就代表1秒。
@Test(timeout = 1000)
    public void squareRoot() {
        calculator.squareRoot(4);
        assertEquals(2, calculator.getResult());
    }

測試結果截圖

      @ignore:該元數據標記的測試方法會被測試運行器忽略。當測試的方法還沒有實現,或者測試的方法已經過時,或者在某種條件下才能測試該方法(比如需要一個數據庫聯接, 而在本地測試的時候,數據庫並沒有連接),那麼使用該標籤來標示這個方法。同時,你可以爲該標籤傳遞一個String的參數,來表明爲什麼會忽略這個測試方法。比如:@lgnore(“該方法還沒有實現”),在執行的時候,僅會提示該方法沒有實現,而不會運行測試方法。

5. 基於Eclipse介紹JUnit的應用

      5.1測試類示例:

//該待測試類,主要實現一些簡單的加,減,乘,除,平方,開方等功能
public class Calculator {
    private static int result; // 靜態變量,用於存儲運行結果
    public void add(int n) {
        result = result + n;
    }
    public void substract(int n) {
        result = result - 1;  //Bug: 正確的應該是 result =result-n
    }
    public void multiply(int n) {
    }         // 此方法尚未寫好
    public void divide(int n) {
        result = result / n;
    }
    public void square(int n) {
        result = n * n;
    }
    public void squareRoot(int n) {
        for (; ;) ;            //Bug : 死循環
    }
    public void clear() {     // 將結果清零
        result = 0;
    }
    public int getResult(){
        return result;
    }
}

        5.2 Eclipse的操作步驟

              注:使用JUnit4

基於Eclipse的JUnit基本使用
步驟 截圖
1. 將JUnit4單元測試包引入這個項目:在該項目上點右鍵,點“屬性”,如圖所示:
2. 在彈出的屬性窗口中,首先在左邊選擇“Java Build Path”,然後到右上選擇“Libraries”標籤,之後在最右邊點擊“Add Library…”按鈕,如圖所示:
3. 選中JUnit Library,如圖所示:
4. 然後在新彈出的對話框中選擇JUnit4並點擊確定,如圖所示,JUnit4軟件包就被包含進我們這個項目了。
5. 生成JUnit測試框架:在Eclipse的Package Explorer中用右鍵點擊該類彈出菜單,選擇“New JUnit Test Case”。如圖所示:
6. 測試類命名及待測試類的選擇,操作細節如圖所示:
7. 點擊“Next”後,系統會自動列出你這個類中包含的方法,選擇你要進行測試的方法。此例中,我們僅對“加、減、乘、除”四個方法進行測試。操作細節如圖所示:

      按照上述操作後,系統會自動生成一個新類CalculatorTest,裏面包含一些空的測試用例。你只需要將這些測試用例稍作修改即可使用。

      5.3 完整的測試類代碼

public class CalculatorTest {   
    private static Calculator calculator = new Calculator();

    @Before
    public void setUp() throws Exception {
        calculator.clear();
    }

    @Test
    public void testAdd() {
        calculator.add(3);
        calculator.add(4);
        assertEquals(7, calculator.getResult());

    }

    @Test
    public void testSubstract() {
        calculator.add(8);
        calculator.substract(3);
        assertEquals(5, calculator.getResult());

    }

    @Ignore("Multiply() Not yet implemented")
    @Test
    public void testMultiply() {
        fail("Not yet implemented");
    }

    @Test
    public void testDivide() {
        calculator.add(8);
        calculator.divide(2);
        assertEquals(4, calculator.getResult());
    }
}
測試結果分析表
操作介紹 在CalculatorTest類上點右鍵,選擇“Run As a JUnit Test”來運行我們的測試,如圖所示
操作截圖
運行結果截圖
結果分析 進度條是紅顏色表示發現錯誤,具體的測試結果在進度條上面有表示“共進行了4個測試,其中1個測試被忽略,一個測試失敗”。

6. 參數化測試

      我們測試的時候會遇到這種情況,某個參數有很多特殊值,如計算一個數的平方,可能這個數可以劃分爲:正數,0,負數。這種情況下,必須編寫三個測試用例,這樣就會比較麻煩。爲了簡化此類測試,JUnit4提出了“參數化測試”的概念,只寫一個測試函數,把這若干情況作爲參數傳遞進去,一次性完成測試:

       6.1 非參數化測試代碼

    public class AdvancedTest { 
        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());
        }
     }

       6.2 參數化測試代碼

    //爲這種測試專門生成一個新的類,而不能與其他測試共用同一個類,此例中我們定義了一個SquareTest類。
    //爲這個類指定一個Runner,而不能使用默認的Runner,@RunWith(Parameterized.class)這條語句就是爲這個類指定了一個ParameterizedRunner
    @RunWith(Parameterized.class)
    public class SquareTest{
        private static Calculator calculator = new Calculator();
        private int param;
        private int result;     

    //定義一個待測試的類,並且定義兩個變量,一個用於存放參數,一個用於存放期待的結果。
    //定義測試數據的集合,也就是上述的data()方法,該方法可以任意命名,但是必須使用@Parameters標註進行修飾。
    @Parameters    
    public static Collection data() {
        return Arrays.asList(new Object[][]{
               {2, 4},
               {0, 0},
               {-3, 9},
        });
    }

    //定義構造函數,其功能就是對先前定義的兩個參數進行初始化
    public SquareTest(int param, int result){
        this.param = param;
        this.result = result;
    }

    @Test    
    public void square(){
        calculator.square(param);
        //執行了3次該測試類,依次採用了數據集合中的數據{處理值,預期處理結果}
        assertEquals(result, calculator.getResult());
    }
 }

       6.3 參數化測試結果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章