淺談測試之JUnit

JUnit是一個java語言的單元測試框架,是java測試裏最基本的框架。java

JUnit的集成

Android Studio建立的工程會自動集成JUnit,在build.gradle中添加相關依賴:git

testImplementation 'junit:junit:4.12'
複製代碼

JUnit的示例

測試框架的存在,並非必須的。它們只是爲了讓咱們寫更少的測試代碼。看下面示例,你會發現,所謂的單元測試方法,就像咱們初學java時,常寫的main方法。github

下面是使用JUnit進行測試的幾個例子。數據庫

//測試一個有返回值的方法
    @Test
    public void testMethod() {
        int actual = Util.add(1, 2);
        assertEquals(3, actual);
    }
    
    //測試一個沒有返回值,有反作用的方法
    @Test
    public void testMethodWithSideEffect() {
        List<String> strings = Arrays.asList("a", "d", "b", "c");
        List<String> excepted = Arrays.asList("a", "b", "c", "d");
        //測試集合工具類的排序方法
        Collections.sort(strings);
        assertEquals(excepted, strings);
    }

    //測試一個方法拋異常的方案1
    @Test
    public void testMethodThrowException(){
        Exception actual = null;
        try {
            Util.throwException();
        }catch (Exception e){
            actual = e;
        }
        assertEquals(IllegalArgumentException.class,actual.getClass());
    }
    
    //測試一個方法拋異常的方案2
    @Test(expected = IllegalArgumentException.class)
    public void testMethodThrowException2() {
        Util.throwException();
    }
複製代碼

如你所見,斷言是單元測試裏經常使用的東西。JUnit經常使用的斷言方法,都在org.junit.Assert類裏面,下面列出常見的幾個斷言方法。顧名思義,就很少說了。安全

assertEquals
assertNotEquals
assertArrayEquals
assertTrue
assertFalse
assertNull
assertNotNull
fail
...
複製代碼

JUnit的註解

相關內容主要來源於JUnit的源碼註釋,若有困惑,請參考源碼註釋。bash

@Test

用於標註public void方法。被這個註解標記的方法,就是一個測試方法。一個測試類裏面,能夠有多個被@Test標註的測試方法。它們應該彼此獨立,互不影響。能夠點方法旁邊的綠色箭頭,單獨運行一個測試方法。app

也能夠點擊當前測試類旁邊的箭頭,執行測試類下面全部的測試方法。框架

還能夠一鍵運行test包下面的全部測試類。ide

注意:有兩種狀況會視爲測試失敗,不然測試成功。工具

1)測試方法拋異常。

2)你能夠這樣使用@Test(timeout = 100)。設置超時時間,若是超時則視爲測試失敗。但這種作法是線程不安全的,因此官方推薦使用{@link org.junit.rules.Timeout} rule來代替。

@Before和@After

它們是方法級別的,用於標註public void方法,會在被@Test標註的測試方法的一前一後運行,每調用一個測試方法都會執行一次,也就是@Before->@Test->@After。因此咱們一般會在被@Before標註的方法下作數據的初始化。在被@After標註的方法下,作數據的清除。

@BeforeClass和@AfterClass

相似@Before和@After,但不一樣的是它們是類級別,也就是在執行一個測試類的時候只會調用一次,並且被它們標註的方法,必須是public static void方法。這些方法只會運行一次,會被當前測試類裏面全部的測試方法共享。當測試都須要一些昂貴的操做的時候,就須要用到這兩個註解。雖然,這會讓測試的獨立性進行了必定的妥協,但有時這是一個有必要的優化操做。好比,數據庫的鏈接和關閉。

@Rule

這是一個很是強大的註解。

@Rule是方法級別的,每一個測試方法執行時都會調用被標註的Rule。

能夠標註是public但非靜態,且是TestRule子類的成員變量,如:

@Rule
public TemporaryFolder folder= new TemporaryFolder();
複製代碼

也能夠標註是public但非靜態,並且必須返回一個TestRule子類的實例的方法,如:

private TemporaryFolder folder= new TemporaryFolder();
@Rule
public TemporaryFolder getFolder() {
    return folder;
}
複製代碼

TestRule是一個接口類,能夠利用它,添加自定義的檢查,或者執行必要的設置或清理。TestRule能夠作@Before、@After、@BeforeClass和@AfterClass這幾個註解能作的全部事,但它每每更強大。

junit也爲咱們提供了幾個TestRule的具體實現,如Timeout、TemporaryFolder。下面給出一個使用示例:

public class Test {
//只須要用@Rule標註一個是TestRule子類的成員變量。
//這樣,若是該類中的任意測試方法超過5000ms任未完成,則該測試失敗。
@Rule
public Timeout timeout = new Timeout(5000);
//其他代碼略...
}
複製代碼

咱們也徹底能夠實現屬於本身的TestRule,將本身測試類裏面經常使用的設置或者清理等重複性高的代碼,封裝進去,簡化測試代碼。

public class YourRule implements TestRule {
    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                //作一些預先的設置,或者任何你想作的事
                //如數據庫表的建立
                ......
                
                //這裏就是測試方法(包括了before、after在裏面)
                //下面是官方源碼裏,對Statement接口的描述
                //Represents one or more actions to be taken at runtime in the course
                //of running a JUnit test suite.
                base.evaluate();  
                
                //作一些清理,或者任何你想作的事
                //如數據庫表的刪除
                ......
            }
        };
    }
}

複製代碼

:若是是對TestRule的具體實現仍然感到迷惑,也能夠參考官方給出的那幾個具體實現。

@ClassRule

@ClassRule和@Rule類似,不一樣點是,@ClassRule是類級別的,只能用於標註靜態成員(成員變量,成員方法),在執行一個測試類的時候只會調用一次被註解的Rule。

@Ingore

被該註解標記的測試方法,會被忽略,不會被運行。

@FixMethodOrder

測試類的執行順序可經過對測試類添加註解 「@FixMethodOrder(value)」 。 三種執行順序可供選擇:

MethodSorters.DEFAULT:默認順序由方法名hashcode值來決定,若是hashcode值同樣,就使用MethodSorters.NAME_ASCENDING來排序。

MethodSorters.NAME_ASCENDING:按字符的字典順序,會始終保持一致。

MethodSorters.JVM:順序可能因運行而異,說白了就是不固定。

感受這是一個很雞肋註解。。

後記

文中的相關測試例子,以及更多的測試例子都可以在UnitTest裏面找到。

若是你對一些知識點理解不透徹,也許參考更多的博客也未必有用。我建議,你應該去好好翻閱一下官方的源碼註釋。這或許能幫助你更深刻理解這些東西,畢竟不少博客的描述,就是源自源碼註釋。

相關文章
相關標籤/搜索