java的單元測試JUnit4


java的單元測試

1. 概念

java單元測試是最小的功能單元測試代碼, 單元測試就是針對單個java方法的測試

java程序的最小功能單元是方法

2. 單元測試的優點

  • main方法進行測試的缺點:

    • 只能有一個main()方法, 不能把測試代碼分離出來
    • 無法打印出測試結果和期望結果.例如: expected: 3628800, but actual: 123456
  • 單元測試的優點:

    • 確保單個方法正常運行
    • 如果修改了方法代碼, 只需要保其對應的單元測試通過就可以了
    • 測試代碼本省就可以作為示例代碼
    • 可以自動化運行所有測試並獲得報告

3. Junit單元測試

JUnit是一個開源的java語言的單元測試框架

專門針對java語言設計, 使用最廣泛, JUnit是標准的單元測試架構

3.1 JUnit特點

  • 使用斷言(Assertion)測試期望結果
  • 可以方便的組織和運行測試
  • 可以方便的查看測試結果
  • 常用的開發工具IDEA, Eclipse都集成了JUnit
  • 可以方便的繼承到maven中

3.2 maven依賴

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
     <!-- junit的版本有3.x, 4.x, 5.x 5.x還沒有發布, 現在都用是4.x -->
</dependency>

3.3 在IDE中使用快捷鍵進行單元測試

測試類的使用目錄必須是如下, 測試類規定標准是在test目錄中進行測試

localhost:javatest lingjing$ tree -d -L 3
.
├── src
│   ├── main
│   │   └── java
│   └── test
│       └── java

IDE的快捷鍵是:ctrl+shift+t --> create new test

然后選擇對應的方法進行測試就好了

3.4 斷言

3.4.1 斷言的例子

斷言的使用, 必須先引入必須的包: IDE自動創建的會自動引入

import static org.junit.Assert.*;

例子: 在main包中的編寫的一個正則表達式的類

import java.util.Arrays;

/**
 * @ClassName Calculator
 * @Description 在main中的主要類
 * @Author lingxiangxiang
 * @Date 10:07 AM
 * @Version 1.0
 **/
public class Calculator {

    public int calculate(String expression) {
        String[] ss = expression.split("\\+");
        System.out.println(expression + " => " + Arrays.toString(ss));
        int sum = 0;
        for (String s: ss) {
            sum += Integer.parseInt(s.trim());
        }
        return sum;
    }
}

測試類:

import org.junit.Test;

import static org.junit.Assert.*;

public class CalculatorTest {

    @Test
    public void calculate() {
        assertEquals(3, new Calculator().calculate("1 + 2"));
        assertEquals(3, new Calculator().calculate("1 + 2 + 3"));
    }
}

測試類執行結果如下:

1 + 2 => [1 ,  2]
1 + 2 + 3 => [1 ,  2 ,  3]

java.lang.AssertionError: 
Expected :3
Actual   :6
 <Click to see difference>


	at javatest.CalculatorTest.calculate(CalculatorTest.java:12)


第一個方法: 1 + 2 => [1 , 2], 最終的結果3是正確的, 所有沒有任何報錯, 正常顯示

第二個方法: 1 + 2 + 3 => [1 , 2 , 3], 最終報錯, 並提示在代碼的位置: CalculatorTest.java:12, 並且羅列出Expected和Actual的值, 清楚的顯示了結果的對比情況, 和代碼出現的位置

3.4.2 斷言的常用方法

assertEquals(100, x): 斷言相等

assertArrayEquals({1, 2, 3}, x): 斷言數組相等

assertEquals(3.1416, x, 0.0001): 浮點數組斷言相等

assertNull(x): 斷言為null

assertTrue(x > 0): 斷言為true

assertFalse(x < 0): 斷言為false;

assertNotEquals: 斷言不相等

assertNotNull: 斷言不為null

3.5 使用@Before和@After

  • 在@Before方法中初始化測試資源
  • 在@After方法中釋放測試資源
  • @BeforeClass: 初始化非常耗時的資源, 例如創建數據庫
  • @AfterClass: 清理@BeforeClass創建的資源, 例如創建數據庫

3.5.1 對於每一個@Test方法的執行順序

注意:** 單個@Test方法執行前會創建新的XxxTest實例, 實例變量的狀態不會傳遞給下一個@Test方法, 單個@Test方法執行前后會執行@Before和@After方法

  1. 執行類的構造函數

  2. 執行@Before方法

  3. 執行@Test方法

  4. 執行@After方法

3.5.2 代碼實例:

寫一個整體的測試類如下:

package javatest;

/**
 * @ClassName SequenceTest
 * @Description TODO
 * @Author lingxiangxiang
 * @Date 1:54 PM
 * @Version 1.0
 **/

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class SequenceTest {

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        System.out.println("BeforeClass()");
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        System.out.println("AfterClass()");
    }

    @Before
    public void setUp() throws Exception {
        System.out.println("    Before()");
    }

    @After
    public void tearDown() throws Exception {
        System.out.println("    After()");
    }

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

    @Test
    public void testA() {
        System.out.println("    testA()");
    }

    @Test
    public void testB() {
        System.out.println("    testB()");
    }

    @Test
    public void testC() {
        System.out.println("    testC()");
    }

}

如果運行整個類, 運行結果如下:

BeforeClass()
  new SequenceTest()
    Before()
    testA()
    After()
  new SequenceTest()
    Before()
    testB()
    After()
  new SequenceTest()
    Before()
    testC()
    After()
AfterClass()

如果運行單個@Test類

BeforeClass()
  new SequenceTest()
    Before()
    testA()
    After()
AfterClass()

3.6 異常測試

異常測試可以通過@Test(expected=Exception.class), 對可能發生的每種類型的異常進行測試

  • 如果拋出了指定類型的異常, 測試成功
  • 如果沒有拋出指定類型的異常, 或者拋出的異常類型不對, 測試失敗

例子:

運行如下代碼: 正常通過

// 運行如下代碼, 正常運行, 確實發生了ArithmeticException異常, 代碼通過
@Test(expected = ArithmeticException.class)
    public void testException() {
       int i = 1 / 0;
    }

運行如下代碼: 有報錯信息

@Test(expected = ArithmeticException.class)
    public void testException() {
       int i = 1 / 1;
    }

執行結果如下:

java.lang.AssertionError: Expected exception: java.lang.ArithmeticException

3.7 參數化測試

@RunWith: 當類被@RunWith注釋修飾, 或者類繼承了一個被該注解類修飾的類, JUnit將會使用這個注解所指明的運行器(runner)來運行測試, 而不是JUni默認的運行器

要進行參數化測試,需要在類上面指定如下的運行器:
  @RunWith (Parameterized.class)

然后,在提供數據的方法上加上一個@Parameters注解,這個方法必須是靜態static的,並且返回一個集合Collection。

JUnit4中參數化測試要點: 
1. 測試類必須由Parameterized測試運行器修飾 
2. 准備數據。數據的准備需要在一個方法中進行,該方法需要滿足一定的要求: 
    1)該方法必須由Parameters注解修飾 
    2)該方法必須為public static的 
    3)該方法必須返回Collection類型 
    4)該方法的名字不做要求 
    5)該方法沒有參數

例子:

@RunWith(Parameterized.class)
public class Testa {

    @Parameterized.Parameters
    public static Collection<?> data() {
        return Arrays.asList(new Object[][] { { "1+2", 3 }, { "1+2+5", 8 }, { "123+456", 579 }, { " 1 + 5 + 10 ", 16 } });
    }

    Calculator calc;

    @Parameterized.Parameter(0)
    public String input;

    @Parameterized.Parameter(1)
    public int expected;

    @Before
    public void setUp() {
        calc = new Calculator();
    }

    @Test
    public void testCalculate() {
        int r = calc.calculate(this.input);
        assertEquals(this.expected, r);
    }

}

執行結果:

1+2 => [1, 2]
1+2+5 => [1, 2, 5]
123+456 => [123, 456]
 1 + 5 + 10  => [ 1 ,  5 ,  10 ]

3.8 超時測試

@Test(timeout=1000)可以設置超時時間

timeout單位是毫秒


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM