深刻探索:單元測試

單元測試這一塊咱們一直都有在接觸,可是對於我來講,還不夠重視或深刻,能夠說是忽視的一塊,如今公司要把測試覆蓋率給推起來,此時正好能夠來探究探究。 JUnit4 單元測試主要有如下的一些功能:html

  • 參數測試
  • 異常測試
  • 超時測試
  • 靈活固件
  • 忽略測試
  • 對測試進行邏輯分組

注意:本版本基於JUnit4.12。java

參數測試

下面咱們會對這樣的一個類作參數測試,咱們需呀一個 參數 和 一個預期結果值git

public class Fibonacci {
    public static int compute(int n) {
        int result = 0;

        if (n <= 1) {
            result = n;
        } else {
            result = compute(n - 1) + compute(n - 2);
        }

        return result;
    }
}

如何作測試?第一個方法是構造函數方式github

@RunWith(Parameterized.class)
public class FibonacciTest {

    @Parameters
    public static Collection<Object[]> data() {
        /* 數組第一個 爲 參數, 第二個爲 指望結果 */
        return Arrays.asList(new Object[][] {{0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}});
    }

    private int fInput;

    private int fExpected;

    public FibonacciTest(int input, int expected) {
        fInput = input;
        fExpected = expected;
    }

    @Test
    public void test() {
        Assert.assertEquals(fExpected, Fibonacci.compute(fInput));
    }
}

非構造函數實現(推薦:非構造函數更加靈活,不會影響類的其餘方法):數組

@RunWith(Parameterized.class)
public class FibonacciTest2 {
    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {{0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}});
    }

    @Parameter // first data value (0) is default
    public /* NOT private */ int fInput; // 數組第一個參數爲輸入參數

    @Parameter(1)
    public /* NOT private */ int fExpected; // 數組第一個參數爲 預期參數

    @Test
    public void test() {
        Assert.assertEquals(fExpected, Fibonacci.compute(fInput));
    }
}

參考:https://github.com/junit-team/junit4/wiki/Parameterized-tests函數

異常測試

在咱們編寫測試用例的過程當中,咱們每每都會有指望異常的測試方法,有異常就是對了。 舉一個例子單元測試

new ArrayList<Object>().get(0);

這樣的方法毫無疑問會爆出IndexOutOfBoundsException 數組越界異常,爲此,咱們要驗證這個異常的出現是正確的,咱們能夠@Test(exceted=IndexOutOfBoundsException.class) 來標記指望的異常。測試

@Test(expected = IndexOutOfBoundsException.class) 
public void empty() { 
     new ArrayList<Object>().get(0); 
}

然而這個只是方法之一,但卻不是推薦的方法,對於更長的測試,建議使用ExpectedException Rule 來實現;ui

對異常進行更深的測試: 上面的方式是一個很是好的示例,可是他是有限制的。例如, 不能在異常中測試消息的值, 也不能在引起異常後檢測域對象的狀態。在Junit3.x 是用 try/catch 來作的(這個不浪費時間敘述),可是在Junit4.x 可使用 @Rule 來實現。使用 ExpectedException 規則。此規則容許您不只指示所指望的異常, 並且還能夠顯示所指望的異常消息。 實現以下:this

public class TestExyRule {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void shouldTestExceptionMessage() throws IndexOutOfBoundsException {
        List<Object> list = new ArrayList<Object>();
        thrown.expect(IndexOutOfBoundsException.class);
        thrown.expectMessage("Index: 0, Size: 0");
        list.get(0); // execution will never get past this line
    }
}

上面例子的expectMessage 可使用 Matchers 來作, 這樣能夠更加的靈活,如:thrown.expectMessage(Matchers.containsString("Size: 0")); 固然咱們也能夠更加進一步的 驗證異常的狀態:

import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class TestExy {
     @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void shouldThrow() {
        TestThing testThing = new TestThing();
        thrown.expect(UnsupportedOperationException.class);
        thrown.expectMessage(startsWith("some Message"));
        testThing.chuck();
    }

    private class TestThing {
        public void chuck() {
            throw new UnsupportedOperationException("some Message");
        }
    }
}

https://github.com/junit-team/junit4/wiki/Exception-testing

超時測試

https://github.com/junit-team/junit4/wiki/Timeout-for-tests 超時測試比較簡單,舉個例子。

@Test(timeout =1000)
public void testMethod() {
    for(;;){}
}

如上面的代碼咱們對時間作了限制爲1s, 可是因爲有死循環,是沒法在規定時間內經過測試的。

靈活固件

https://github.com/junit-team/junit4/wiki/Aggregating-tests-in-suites

邏輯分組測試

https://github.com/junit-team/junit4/wiki/Categories

參考

相關文章
相關標籤/搜索