JUnit4教程+實踐

1、什麼是JUnit?

JUnit是Java編程語言的單元測試框架,用於編寫和可重複運行的自動化測試。java

2、JUnit特色:
  • JUnit 是一個開放的資源框架,用於編寫和運行測試。
  • 提供註解來識別測試方法。
  • 提供斷言來測試預期結果。
  • JUnit 測試容許你編寫代碼更快,並能提升質量。
  • JUnit 優雅簡潔。沒那麼複雜,花費時間較少。
  • JUnit測試能夠自動運行而且檢查自身結果並提供即時反饋。因此也沒有必要人工梳理測試結果的報告。
  • JUnit測試能夠被組織爲測試套件,包含測試用例,甚至其餘的測試套件。
  • JUnit在一個條中顯示進度。若是運行良好則是綠色;若是運行失敗,則變成紅色。
3、JUnit註解
註解 描述
@Test 測試註解,標記一個方法能夠做爲一個測試用例 。
@Before Before註解表示,該方法必須在類中的每一個測試以前執行,以便執行某些必要的先決條件。
@BeforeClass BeforeClass註解指出這是附着在靜態方法必須執行一次並在類的全部測試以前,這種狀況通常用於測試計算、共享配製方法(如數據庫鏈接)。
@After After註釋表示,該方法在每項測試後執行(如執行每個測試後重置某些變量,刪除臨時變量等)。
@AfterClass 當須要執行全部測試在JUnit測試用例類後執行,AlterClass註解可使用以清理一些資源(如數據庫鏈接),注意:方法必須爲靜態方法。
@Ignore 當想暫時禁用特定的測試執行可使用這個註解,每一個被註解爲@Ignore的方法將再也不執行
@Runwith @Runwith就是放在測試類名以前,用來肯定這個類怎麼運行的。也能夠不標註,會使用默認運行器。
@Parameters 用於使用參數化功能。
@SuiteClasses 用於套件測試
4、JUnit斷言
斷言 描述
void assertEquals([String message],expected value,actual value) 斷言兩個值相等。值類型多是int,short,long,byte,char,Object,第一個參數是一個可選字符串消息
void assertTrue([String message],boolean condition) 斷言一個條件爲真
void assertFalse([String message],boolean condition) 斷言一個條件爲假
void assertNotNull([String message],java.lang.Object object) 斷言一個對象不爲空(null)
void assertNull([String message],java.lang.Object object) 斷言一個對象爲空(null)
void assertSame([String message],java.lang.Object expected,java.lang.Object actual) 斷言兩個對象引用相同的對象
void assertNotSame([String message],java.lang.Object unexpected,java.lang.Object actual) 斷言兩個對象不是引用同一個對象
void assertArrayEquals([String message],expectedArray,resultArray) 斷言預期數組和結果數組相等,數組類型多是int,short,long,byte,char,Object

讓咱們看下使用斷言的例子。 AssertionTest.javaspring

public class AssertionTest {

    @Test
    public void test() {
        String obj1 = "junit";
        String obj2 = "junit";
        String obj3 = "test";
        String obj4 = "test";
        String obj5 = null;
        
        int var1 = 1;
        int var2 = 2;

        int[] array1 = {1, 2, 3};
        int[] array2 = {1, 2, 3};

        Assert.assertEquals(obj1, obj2);

        Assert.assertSame(obj3, obj4);
        Assert.assertNotSame(obj2, obj4);
        
        Assert.assertNotNull(obj1);
        Assert.assertNull(obj5);

        Assert.assertTrue(var1 < var2);
        Assert.assertFalse(var1 > var2);

        Assert.assertArrayEquals(array1, array2);

    }
}
複製代碼

在以上類中咱們能夠看到,這些斷言方法是能夠工做的。數據庫

  • assertEquals() 若是比較的兩個對象是相等的,此方法將正常返回;不然失敗顯示在JUnit的窗口測試將停止。
  • assertSame() 和 assertNotSame() 方法測試兩個對象引用指向徹底相同的對象。
  • assertNull() 和 assertNotNull() 方法測試一個變量是否爲空或不爲空(null)。
  • assertTrue() 和 assertFalse() 方法測試if條件或變量是true仍是false。
  • assertArrayEquals() 將比較兩個數組,若是它們相等,則該方法將繼續進行不會發出錯誤。不然失敗將顯示在JUnit窗口和停止測試。
5、JUnit執行過程

JuntiTest.java編程

public class JunitTest {

    @BeforeClass
    public static void beforeClass() {
        System.out.println("in before class");
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("in after class");
    }

    @Before
    public void before() {
        System.out.println("in before");
    }

    @After
    public void after() {
        System.out.println("in after");
    }

    @Test
    public void testCase1() {
        System.out.println("in test case 1");
    }

    @Test
    public void testCase2() {
        System.out.println("in test case 2");
    }

}
複製代碼

經過idea執行整個測試類後,執行結果:數組

in before class
in before
in test case 1
in after
in before
in test case 2
in after
in after class
複製代碼
6、忽略測試
  • 一個帶有@Ignore註解的測試方法不會被執行
  • 若是一個測試類帶有@Ignore註解,則它的測試方法將不會被執行

咱們把剛纔測試類中的testCase2()方法標記爲@Ignore,bash

@Ignore
    @Test
    public void testCase2() {
        System.out.println("in test case 2");
    }
複製代碼

而後在執行測試類的時候就會忽視這個方法,結果爲:框架

in before class
in before
in test case 1
in after

Test ignored.
in after class
複製代碼
7、時間測試

JUnit提供了一個暫停的方便選項,若是一個測試用例比起指定的毫秒數花費了更多的時間,那麼JUnit將自動將它標記爲失敗,timeout參數和@Test註解一塊兒使用,例如@Test(timeout=1000)。 繼續使用剛纔的例子,如今將testCase1的執行時間延長到5000毫秒,並加上時間參數,設置超時爲1000毫秒,而後執行測試類編程語言

@Test(timeout = 1000)
    public void testCase1() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5000);
        System.out.println("in test case 1");
    }
複製代碼

testCase1被標記爲失敗,而且拋出異常,執行結果:ide

in before class
in before
in after

org.junit.runners.model.TestTimedOutException: test timed out after 1000 milliseconds

	at java.lang.Thread.sleep(Native Method)
	at java.lang.Thread.sleep(Thread.java:340)
	at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
	at com.lxs.JUnit.JunitTest.testCase1(JunitTest.java:35)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298)
	at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.lang.Thread.run(Thread.java:748)

in before
in test case 2
in after
in after class
複製代碼
8、異常測試

Junit 用代碼處理提供了一個追蹤異常的選項。你能夠測試代碼是否它拋出了想要獲得的異常。expected 參數和 @Test 註釋一塊兒使用。如今讓咱們看看 @Test(expected)。新建測試方法testCase3()。函數

@Test(expected = ArithmeticException.class)
    public void testCase3() {
        System.out.println("in test case 3");
        int a = 0;
        int b = 1 / a;
    }
複製代碼

單獨執行testCase3()方法,因爲獲得了一個預期異常,因此測試經過,結果爲

in before class
in before
in test case 3
in after
in after class
複製代碼

若是沒有獲得預期異常:

in before class
in before
in test case 3
in after

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

in after class
複製代碼
9、參數化測試

Junit 4 引入了一個新的功能參數化測試。參數化測試容許開發人員使用不一樣的值反覆運行同 一個測試。你將遵循 5 個步驟來建立參數化測試:

-爲準備使用參數化測試的測試類指定特殊的運行器 org.junit.runners.Parameterized。

  • 爲測試類聲明幾個變量,分別用於存放指望值和測試所用數據。
  • 爲測試類聲明一個帶有參數的公共構造函數,並在其中爲第二個環節中聲明的幾個變量賦值。
  • 爲測試類聲明一個使用註解 org.junit.runners.Parameterized.Parameters 修飾的,返回值爲 java.util.Collection 的公共靜態方法,並在此方法中初始化全部須要測試的參數對。
  • 編寫測試方法,使用定義的變量做爲參數進行測試。
什麼是@RunWith?

首先要分清幾個概念:測試方法、測試類、測試集、測試運行器。

  • 其中測試方法就是用@Test註解的一些函數。
  • 測試類是包含一個或多個測試方法的一個**Test.java文件,
  • 測試集是一個suite,可能包含多個測試類。
  • 測試運行器則決定了用什麼方式偏好去運行這些測試集/類/方法。

而@Runwith就是放在測試類名以前,用來肯定這個類怎麼運行的。也能夠不標註,會使用默認運行器。常見的運行器有:

  • @RunWith(Parameterized.class) 參數化運行器,配合@Parameters使用JUnit的參數化功能
  • @RunWith(Suite.class) @SuiteClasses({ATest.class,BTest.class,CTest.class}) 測試集運行器配合使用測試集功能
  • @RunWith(JUnit4.class), junit4的默認運行器
  • @RunWith(JUnit38ClassRunner.class),用於兼容junit3.8的運行器
  • 一些其它運行器具有更多功能。例如@RunWith(SpringJUnit4ClassRunner.class)集成了spring的一些功能

PrimeNumberCheckerTest.java

/**
 * 步驟一: 指定定參數運行器
 */
@RunWith(Parameterized.class)
public class PrimeNumberCheckerTest {

    /**
     * 步驟二:聲明變量
     */
    private Integer inputNumber;
    private Boolean expectedResult;
    private PrimeNumberChecker primeNumberChecker;

    /**
     * 步驟三:爲測試類聲明一個帶有參數的公共構造函數,爲變量賦值
     */
    public PrimeNumberCheckerTest(Integer inputNumber,
                                  Boolean expectedResult) {
        this.inputNumber = inputNumber;
        this.expectedResult = expectedResult;
    }

    /**
     * 步驟四:爲測試類聲明一個使用註解 org.junit.runners.Parameterized.Parameters 修飾的,返回值爲
     * java.util.Collection 的公共靜態方法,並在此方法中初始化全部須要測試的參數對
     *   1)該方法必須由Parameters註解修飾 
          2)該方法必須爲public static的 
          3)該方法必須返回Collection類型 
          4)該方法的名字不作要求 
          5)該方法沒有參數 
     */
    @Parameterized.Parameters
    public static Collection primeNumbers() {
        return Arrays.asList(new Object[][]{
                {2, true},
                {6, false},
                {19, true},
                {22, false},
                {23, true}
        });
    }

    @Before
    public void initialize() {
        primeNumberChecker = new PrimeNumberChecker();
    }

    /**
     * 步驟五:編寫測試方法,使用自定義變量進行測試
     */
    @Test
    public void testPrimeNumberChecker() {
        System.out.println("Parameterized Number is : " + inputNumber);
        Assert.assertEquals(expectedResult,
                primeNumberChecker.validate(inputNumber));
    }
}
複製代碼

PrimeNumberChecker.java

public class PrimeNumberChecker {

    public Boolean validate(final Integer parimeNumber) {
        for (int i = 2; i < (parimeNumber / 2); i++) {
            if (parimeNumber % i == 0) {
                return false;
            }
        }
        return true;
    }
}
複製代碼

JUnit會按照設置的參數屢次執行,執行結果:

Parameterized Number is : 2
Parameterized Number is : 6
Parameterized Number is : 19
Parameterized Number is : 22
Parameterized Number is : 23
複製代碼
10、套件測試

「套件測試」是指捆綁了幾個單元測試用例並運行起來。在JUnit中,@RunWith 和 @Suite 這兩個註解是用來運行套件測試。先來建立幾個測試類

public class JunitTest1 {

    @Test
    public void printMessage(){
        System.out.println("in JunitTest1");
    }
}
複製代碼
public class JunitTest2 {

    @Test
    public void printMessage(){
        System.out.println("in JunitTest2");
    }
}
複製代碼
@RunWith(Suite.class)
@Suite.SuiteClasses({
        /**
         * 此處類的配置順序會影響執行順序
         */
        JunitTest1.class,
        JunitTest2.class
})
public class JunitSuite {

}
複製代碼

執行JunitSuite測試類,執行結果:

in JunitTest1
in JunitTest2
複製代碼
相關文章
相關標籤/搜索