上一篇簡單說明基本測試的概念跟要怎麼建立測試程式在 Spring Boot 之後,這邊就來接著提供一些測試的設計原則和一些方法。

3A 原則 (3A Pattern)

  • Arrange: 初始化物件、要用到的參數
  • Act: 呼叫要測試的方法
  • Assert: 驗證測試結果

如果以上一篇的範例來看,我們要測試加法的功能會這樣設計就是應用到 3A 原則

  • Arrange:首先就是要先建立好測試的環境,把要用到的物件初始化,建立好相關的參數,也就是我們引入 Calculator 這個物件進入並且建立好要執行加法的參數。
  • Act:接著呼叫測試的方法並且帶入我們要的參數
  • Assert:利用斷言的方法來驗證,是否符合預期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CalculatorTest {

@Test
void testAdd() {
// Arange
Calculator calc = new Calculator();
int x = 1;
int y = 1;

// Act
int result = calc.add(x, y);

// Assert
assertEquals(2, result);
}
}

常見斷言應用

斷言方法 說明
assertEquals(A, B) 預期 A 和實際 B 值相等,等同使用 equals() 方法比較,A和B 是基本類型
assertNotEquals(A, B) 預期 A 和實際 B 值不相等
assertTrue(A) A 條件判斷為 true
assertFalse(A) A 條件判斷為 false
assertNull(A) A 物件為空值
assertNotNull(A) A 物件不為空值
assertThrows(exception, method) 預期拋出 exception,method 為執行的方法,當執行該方法拋出對應的 exception 就會通過

如果接著我們打算擴充 Calculator 並且進行測試,多一個除法的功能,並且除以0會拋出 IllegalArgumentException

1
2
3
4
5
6
public int divide(int x, int y) {
if (y == 0) {
throw new IllegalArgumentException("不能除以 0");
}
return x / y;
}

這邊就可以應用到那面那些方法,這邊也加入 message 可以協助我們沒通過出錯時會跳出對應的訊息,像是我這邊在 assertEquals, assertNotEquals 後面加入的訊息

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void testDivide() {
Calculator calc = new Calculator();
int result = calc.divide(2,2);
assertEquals(1, result, "result should be 1");
assertNotEquals(0, result, "result should not be 0");
assertTrue(result > 0);
assertFalse(result != 1);
assertThrows(IllegalArgumentException.class, () -> {
calc.divide(2,0);
});
}

正常上面的 assert 都會通過。
如果 assertEquals 有出錯,假設我們把 1 改成 2 assertEquals(2, result, "result should be 1");
就可以看到 console 有把這段錯誤提示印出來
https://ithelp.ithome.com.tw/upload/images/20240927/20150977O6veBDLhQF.png

特別要說明就是 assertThrows() 這個方法需要放入第1個參數是 Exception.class,第2個用 lamda 表達式,把要執行驗證的方法加入到 ( )→{ } 的 { } 裡面。

大致上基本的設計原則還有 Junit 5 的斷言用法就介紹到這邊,下一篇會介紹進階使用 Mock 的部分。

補充 Intellij test coverage

這邊可以小補充一下 Intellij 有提供一個功能可以知道我們測試的覆蓋程度,這對於撰寫測試時式一個很好的指標參考,如果你的方法裡面有很多判斷或是條件,他會告訴你目前寫的測試大概涵蓋多少,如果把我們的剛剛寫的範例拿來測試。

在要執行的方法點選右鍵,可以看到用 Run test with Coverage
https://ithelp.ithome.com.tw/upload/images/20240927/20150977SzhUizxYoa.png

可以看到有顯示目前覆蓋的百分比,只有 50 %
https://ithelp.ithome.com.tw/upload/images/20240927/20150977wriwyLzW9W.png

可以直接點擊右方項目跳到被測試的區域,並且給予顏色標記哪些有被測試到。
這邊注意到因為我們點 testDivide 所以沒有執行到 testAdd,所以他也標記出 add 方法沒被測。
https://ithelp.ithome.com.tw/upload/images/20240927/201509779yM3PJCf5U.png

解開註解後,包含 Exception 的測試後,確實覆蓋率有提升
https://ithelp.ithome.com.tw/upload/images/20240927/20150977L8DWvbNT4L.png

剩下沒滿足是因為我們只有執行 testDivide ,如果點選整個 CalculatorTest 的測試就會達到 100%
https://ithelp.ithome.com.tw/upload/images/20240927/20150977BHV1PYkPLZ.png


參考資料: