單元測試(二)測試框架:Junit

一、概述

JUnit是一個Java語言的單元測試框架。JUnit有它自己的JUnit擴展生態圈。多數Java的開發環境都已經集成了JUnit作爲單元測試的工具。
JUnit是由 Erich Gamma 和 Kent Beck 編寫的一個迴歸測試框架(regression testing framework)。Junit測試是程序員測試,即所謂白盒測試,因爲程序員知道被測試的軟件如何(How)完成功能和完成什麼樣(What)的功能。Junit是一套框架,繼承TestCase類,就可以用Junit進行自動測試了。
Junit促進了“先測試後編碼”的理念,籤掉建立測試數據的一段代碼,可以先測試然後再應用,增加程序員產量和穩定性,可以減少程序員壓力和花費在排錯上的時間。
使用JUnit,需要在maven的pom文件中添加Junit的依賴(非maven項目導入Junitjar包):

<dependencies>
	[...]
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	[...]
</dependencies>

或者springboot項目中(springcloud微服務項目)maven的pom文件中導入springboot的測試依賴綜合依賴也可涵蓋junit的依賴:

<dependencies>
	[...]
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<version>2.1.5.RELEASE</version>
		</dependency>
	[...]
</dependencies>

或者:

<dependencies>
	[...]
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-test</artifactId>
			<version>2.1.5.RELEASE</version>
		</dependency>
	[...]
</dependencies>

二、框架構成

Junit的測試類包含測試方法,測試方法帶有斷言,當需要一次運行多個測試類時就需要創建測試集(test suit或者Suite來打包多個測試類),Runner形成Junit框架的核心。

  • 測試類

包含一個或多個測試方法的類爲測試類,測試方法即用@Test註解的方法,使用一個測試類可以把類的行爲歸爲一組。
Junit在調用每個@Test方法前爲測試類創建一個新的實例,提供測試方法之間的獨立性。
測試類提供了在所有測試調用指令前發起的setUp方法,在所有測試方法運行完後的tearDown方法,便於測試各種複雜場景。

  • 測試集

把多個測試類歸爲一組方式爲測試集。
如果沒有爲測試類定義一個測試集,那麼junit默認會自動提供一個測試集包含測試類的所有測試。通常使用測試集將同一個包中測試類整合爲一個測試集百年與運行。
在Junit中** @RunWith和@Suite **都被組合用作運行測試集。
測試集寫法遵循原則:
1.創建一個空類作爲測試集的入口
2.使用RunWith和SuiteClass來修飾這個空類
3.將Suite作爲參數傳給RunWith,@RunWith(Suite.class)
4.將需要集合到一起運行的測試類作爲數組傳遞給SuiteClassess,@SuiteClassess({xxx1Test.class,xxx2Test.class…})

@RunWith(Suite.class)
@Suite.SuiteClasses(value={XXX1Test.class,XXX2Test.class...})
public class AllOrderTestSuite{
}
  • 測試運行器(Runner)

要運行一個基礎的測試類,不需要特別配置Junit會爲你使用默認測試運行器來管理你的測試類的生命週期,包括創建類、調用測試方法等。BlockJUnit4ClassRunner是在沒指定其它Runner的情況下的默認Runner
但是默認的測試運行器每次只能運行一個測試方法,且在複雜業務時方法中的對象會互相依賴引用時默認的Junit運行器無法管理複雜的調用關係,因此Junit提供了各種測試運行器。使用@RunWith可以指定運行測試類的運行器,常見的運行器有如下幾種:
1.JUnit4運行器:當前版本的JUnit中調用默認的JUnit 4運行器
2.Suite運行器:能同時運行多個測試類的所有測試方法的套件運行器
3.SpringJUnit4ClassRunner:測試運行於Spring環境,在測試類中可以使用Spring的依賴注入事務等Spring框架特有的功能
4.Parameterized:參數測試
5.MockitoJUnitRunner:自動地初始化mock,通常作爲PowerMock測試類的運行器
相關參考:
Runner啓動代碼分析
各常用運行器及運行器使用區別

三、常用API


    @Test
    public void testAssertionsApi(){
        String str1 = new String("abc");
        String str2 = new String("abc");
        String str3 = null;
        String str4 = "abc";
        String str5 = "abc";
        int val1 = 5;
        int val2 = 6;
        String[] array1 = {"one","two","three"};
        String[] array2 = {"one","two","three"};
        String[] array3 = {"one","three","two"};

        //判斷兩個對象是否相同(使用對象的equal方法比較,A.equals(B))
        assertEquals(str1,str2);
        assertEquals(str1,str4);
        
        //判斷兩個對象是否爲同一實例(A == B,引用指向同一對象)
        assertSame(str4,str5);
        assertNotSame(str1,str4);
        
        //判斷是否爲空
        assertNull(str3);
        assertNotNull(str1);
        
        //判斷條件是否成立
        assertTrue(val1 < val2);
        assertFalse(val1 > val2);
        
        //判斷數組是否相同(判斷順序爲 ary1 == ary2 => 是否爲空 =》 長度是否相等 =》 遍歷同一下標的對象是否相等 ...ary[i].equal(ary2[i]))
        assertArrayEquals(array1,array2);
        //assertArrayEquals(array1,array3);失敗
        
        //assertThat(T,March()),注意導包時使用org.hamcrest
        assertThat(val1,allOf(greaterThan(2),lessThan(8)));
        
        //fail()讓測試失敗
        // 一般用於測試不應達到的錯誤分支,正常測試用例不使用
    }
  • TestCase測試案例

    在進行單元測試的時候,在JUNIT4之前,我們需要測試的代碼所在的類一般都需要直接或者間接繼承自TestCase,TestCase繼承自Assert類實現了Test接口,因此TestCase中可以直接使用Assert中的相關方法,使用Test接口的run執行案例。
    需要注意在我們這個類的測試流程,假設我們創建的TestCase子類中有兩個測試用例testMethod1和testMethod2,對於我們類中的兩個測試用例testMethod1和testMethod2,都會分別創建一個新的TestCase子類對象,並引起TestCase中的setUp和tearDown函數分別執行一遍,因此,在進行單元測試的過程中,我們可以在setUp當中進行一些初始化操作(如類的某些屬性的賦值操作),在tearDown中進行一些掃尾工作(如類中某些對象所持有資源的釋放)。
    TestCase類中常用重要方法如下:

    • countTestCases():被run執行的測試案例計數
    • createResult():創建默認的TestResult
    • getName():獲取TestCase的名稱
    • run()/run(TestResult result):運行測試案例並收集結果
    • setUp():測試案例執行前初始化
    • tearDown():測試案例執行完成後
    • toString():返回測試案例的一個字符串表示

tips:TestCase調用數序爲:setUp->testXXX1->tearDown;setUp->testXXX2->tearDown;…

執行TestCase
1.使用JUnitCore.run來執行並分析結果:

public static void main(String[] args){
	Result  result = JUnitCore.run(xxxMyTest1.class);
	//輸出測試結果
	for(Failure fail: result.getFailures()){
		Sytem.out.pringln(fail.toString());
	}
}

2.使用TestCase自帶的run運行測試案例(每次必須指定測試方法名,否則會報找不到對應測試方法的錯):

public class JunitApiTest extends TestCase {
	 public void testAssertionsApi(){
	 	....}
 public static void main(String[] args) {
        JunitApiTest test = new JunitApiTest();
        test.setName("testAssertionsApi");
        TestResult result = test.run();
        System.out.println(result.toString());
  }

3.idea中在測試類上直接執行測試用例(繼承TestCase後類和testXXX方法變爲可執行的測試案例)

JUNIT4中可以直接使用@Test註解更靈活方便的創建和執行單元測試測試案例,無需繼承TestCase,Junit4雖然也支持TestCase這種寫法,但是TestCase更適用與需要與JUnit 3(和/或Java 5之前的Java版本)兼容的情況,否則更建議使用使用JUNIT4的@Test寫法,更容易使用各種開發工具執行和調試,也有了更多的拓展。
tips:新舊版本測試用例區別與使用請參考此博文

  • TestResult

TestResult類收集所有執行測試案例的結果。TestResult使用了java設計模式的Collecting Parameter模式,TestResult是收集很多運行的Test的運行結果,這裏就需要對於這些運行結果進行管理,則TestResult類定義瞭如下相關的方法:

public synchronized void addError(Test test, Throwable t)    //新增一個錯誤到ArrayList<TestFailure>。

public synchronized void addFailure(Test test, AssertionFailedError t)  //新增一個失敗到ArrayList<TestFailure>。
public synchronized void addListener(TestListener listener)   //在一個test中註冊一個監聽器到ArrayList<TestListener>,//這個監聽器就是TestListener,實現類是TestRunner。

public synchronized void removeListener(TestListener listener)   //從一個test中取消這個監聽器。

private synchronized List<TestListener> cloneListeners()   // 克隆一批監聽器。

tips:TestResult詳細方法分析參考此文

四、常用註解

  • @Test

將一個普通方法修飾成一個測試方法,
@Test(excepted=xx.class): xx.class表示異常類,表示測試的方法拋出此異常時,認爲是正常的測試通過
@Test(timeout=毫秒數) :測試方法執行時間是否符合預期

  • @BeforeClass

會在所有的方法執行前被執行,static方法

  • @AfterClass

會在所有的方法執行之後進行執行,static方法

  • @Before

會在每一個測試方法被運行前執行一次

  • @After

會在每一個測試方法運行後被執行一次

  • Ignore

所修飾的測試方法會被測試運行器忽略

  • @RunWith

可以配置更改測試運行器org.junit.runner.Runner

  • @Parameters

用於使用參數化功能。

tips:註解執行順序
beforeClass->before->testXXX1->after;before->testXXX2->after;…afterClass;

其他相關

junit版本升級到了5了,junit5比junit4做了更多模塊化的框架,添加了更多的更豐富的註解。如有更復雜測試需求,自行學習。

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