IDEA Maven專案利用Junit4進行單元測試
最近在開發專案的時候需要寫單元測試,之前一直沒有接觸過,於是從零開始入門學習,查了網上相關資料,總結成為筆記,在此感謝各位大佬的詳細資料!!!
目錄
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工具窗和編輯器中也會顯示。
參考資料: