1. 程式人生 > >IDEA Maven專案利用Junit4進行單元測試

IDEA Maven專案利用Junit4進行單元測試

    最近在開發專案的時候需要寫單元測試,之前一直沒有接觸過,於是從零開始入門學習,查了網上相關資料,總結成為筆記,在此感謝各位大佬的詳細資料!!!

目錄

0、背景

2、實踐

補充:

0、背景

    我們在寫好一個函式或者類以後,需要檢驗我們的程式是否存在bug或者是否滿足我們的需求,通常的做法就是將寫好的函式在mian方法中呼叫,輸入一些測試用例進行檢驗。當要檢驗的方法數量較少時,這種方法可行,但是當我們有大量的函式需要驗證時,該方法就顯得笨重且繁瑣,往往需要我們人工檢查輸出的結果是否正確等,比較混亂。因此,單元測試就是用來解決這種繁瑣問題的。

1、單元測試簡介

    單元測試是對一個函式、一個類、一個模組甚至是一個系統進行正確性檢驗對過程。

2、實踐

(1)建立專案

我建立的專案名稱為junit_test_demo,並建立了一個名為Junit_Test_Demo的類,新增如下程式碼:

public class Junit_Test_Demo {

    // 加法
    public int add(int a, int b) {
        return a + b;
    }

    // 減法
    public int subtract(int a, int b) {
        return a - b;
    }

    // 乘法
    public int multiply(int a, int b) {
        return a * b;
    }

    // 除法
    public double divide(int a, int b) throws Exception {
        if (b == 0) {
            throw new Exception("除數不能為零!");
        }
        else {
            return a / b;
        }
    }
}

(2)建立Junit_Test_Demo的單元測試

A. 配置junit4的Maven依賴

在pom.xml檔案中新增如下內容,並設定自動匯入專案依賴:

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

B.  將游標置於要新增單元測試的類名上,使用Cmd+shift+T快捷鍵,選擇Create New Test...

C.  在彈出的對話方塊中勾選要新增單元測試的函式,點選OK

D.  此時會在專案的test目錄下建立相應的單元測試類(一般命名規則:類名+Test),如Junit_Test_DemoTest,然後在相應的函式中新增測試程式碼如下:

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

import static org.junit.Assert.*;

public class Junit_Test_DemoTest {

    @Before
    public void setUp() throws Exception {
        System.out.println("單元測試開始前相關操作...");
    }

    @After
    public void tearDown() throws Exception {
        System.out.println("單元測試結束後相關操作...");
    }

    @Test
    public void add() {
        /**
         * assertEquals函式
         * first param: Expected value  期望返回值
         * second param: Actual value   實際返回值
         */
        assertEquals(8, new Junit_Test_Demo().add(2,6));
    }

    @Test
    public void subtract() {
        assertEquals(7, new Junit_Test_Demo().subtract(9,2));
    }

    @Test
    public void multiply() {
        assertEquals(36, new Junit_Test_Demo().multiply(6,6));
    }

    @Test
    public void divide() throws Exception {
        /**
         * assertEquals函式
         * first param: Expected value  期望返回值
         * second param: Actual value   實際返回值
         * third param: delta value     誤差範圍,因為double或float型別值無法直接進行比較,滿足一定誤差範圍即認為兩者相等
         */
        assertEquals(2, new Junit_Test_Demo().divide(8,4),0.001);
    }
}

(3)執行單元測試

A. 點選Run Junit_Test_DemoTest,如果沒有錯誤,全部測試通過,執行結果如下:

B. 下面我們修改一下multiply的測試數值,將第一個6改成4,目的讓測試不通過,看會是什麼結果:提示1個測試失敗,3個通過,並給出了失敗的詳細原因。

未完待續。。。

補充:

1、關於Junit_Test_DemoTest需要注意:

(1)所有測試方法返回型別必須是void且無引數;

(2)一個方法之所以為測試方法,是由@Test來註解的;

(3)assertEquals方法作用是比較兩個引數是否相等,測試的時候應該多選幾個測試數值,比如臨界值等;

(4)assertEquals方法不止可以比較兩個int型引數,還可以比較其它型別引數,有多種過載形式;

2、幾個常用的註解

(1)@Test:將一個方法標記為測試方法;

(2)@Before:每一個測試方法呼叫前必執行的方法;

(3)@After:每一個測試方法呼叫後必執行的方法;

(4)@BeforeClass:所有測試方法呼叫前執行一次,在測試類沒有例項化之前就已被載入,需用static修飾;

(5)@AfterClass:所有測試方法呼叫後執行一次,在測試類沒有例項化之前就已被載入,需用static修飾;

(6)@Ignore:暫不執行該方法;

現在我們來測試一下每個註解,修改單元測試類Junit_Test_DemoTest,修改內容如下:

  • 增加一個建構函式Junit_Test_DemoTest;

  • 增加函式setUpBeforeClass,並用@BeforeClass註解;

  • 增加函式setUpAfterClass,並用@AfterClass註解;

  • 將測試函式multiply用@Ignore註解;

import org.junit.*;

import static org.junit.Assert.*;

public class Junit_Test_DemoTest {

    public Junit_Test_DemoTest() {
        System.out.println("建構函式...");
    }

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

    @AfterClass
    public static void setUpAfterClass() {
        System.out.println("AfterClass...");
    }

    @Before
    public void setUp() throws Exception {
        System.out.println("單元測試開始前相關操作...");
    }

    @After
    public void tearDown() throws Exception {
        System.out.println("單元測試結束後相關操作...");
    }

    @Test
    public void add() {
        /**
         * assertEquals函式
         * first param: Expected value  期望返回值
         * second param: Actual value   實際返回值
         */
        assertEquals(8, new Junit_Test_Demo().add(2,6));
    }

    @Test
    public void subtract() {
        assertEquals(7, new Junit_Test_Demo().subtract(9,2));
    }

    @Ignore
    public void multiply() {
        assertEquals(36, new Junit_Test_Demo().multiply(6,6));
    }

    @Test
    public void divide() throws Exception {
        /**
         * assertEquals函式
         * first param: Expected value  期望返回值
         * second param: Actual value   實際返回值
         * third param: delta value     誤差範圍,因為double或float型別值無法直接進行比較,滿足一定誤差範圍即認為兩者相等
         */
        assertEquals(2, new Junit_Test_Demo().divide(8,4),0.001);
    }
}

執行結果如下:

從結果中得知:

  • @BeforClass和@AfterClass在構造方法前被呼叫了,且只調用了一次,一般用來初始化和關閉資源;

  • @Before和@After在每個@Test執行前後被呼叫

  • @Ignore被忽略;

  • 建構函式執行了三次、三次、三次,這是為什麼?這是因為Junit4為了保證每個測試方法都是單元測試,互不影響,在每個測試方法被呼叫前都會初始化出一個新的例項物件來執行。

3、@Test的一些屬性

  • excepted屬性

excepted屬性是用來測試異常的,即如果被測試的方法沒有丟擲異常,測試不通過,丟擲異常,則測試通過。

我們在單元測試類中新增異常測試方法:

@Test (expected = Exception.class)
    public void testDivideException() throws Exception {
        new Junit_Test_Demo().divide(3,0);
        fail("除數為零沒有丟擲異常");
    }

    該測試方法是(expected = Exception.class)和fail(“除數為零沒有丟擲異常”),會檢查是否丟擲Exception異常(也可以檢查其他異常)。如果丟擲異常測試通過,沒有丟擲異常測試不通過執行fail(“除數為零沒有丟擲異常”)。

  • timeout屬性

該方法是用來測試效能的,測試一個方法能不能在規定時間內完成。用法和expected一樣。

 @Test (timeout = 1000)
    public void testDivideTimeout() throws Exception {
        new Junit_Test_Demo().divide(6,3);
    }

4、程式碼覆蓋率

    收集覆蓋率,通過Run→Run ‘Junit_Test_DemoTest’ with Coverage,執行結束後,IDEA將會在Projec工具視窗顯示每個程式包、類的覆蓋率資料,同時在Coverage工具窗和編輯器中也會顯示。

參考資料: