6月5日引擎測試套件指南
1. 概述
引擎測試工具包允許我們執行測試計劃,並根據需要收集不同詳細程度的統計資料和報告。例如,它可以概覽有多少測試通過,有多少測試失敗。或者,我們可以檢查各個測試結果是否符合預期。
在本教程中,我們將了解 JUnit 5 的引擎測試工具包是什麼,以及如何在我們的應用程式中使用它。
2. 範例測試類
首先,我們需要一個測試類別來運作並收集相關資訊。為了使收集到的信息更有意義,我們需要包含通過、失敗、跳過和中止四種情況的測試。
首先,我們定義一個用於測試的小Object ,一個具有Platform和height Display :
public class Display {
private final Platform platform;
private final int height;
// standard constructor, getters and setters
}
接下來我們來編寫Platform枚舉:
public enum Platform {
DESKTOP,
MOBILE
}
我們將使用剛剛定義的平台,以便編寫僅在行動顯示器上運行的測試。現在我們有了測試Objects ,讓我們在測試類別中使用它們:
public class DisplayTest {
private final Display display = new Display(Platform.DESKTOP, 1000);
@Test
void whenCorrect_thenSucceeds() {
assertEquals(1000, display.getHeight());
}
@Test
void whenIncorrect_thenFails() {
assertEquals(500, display.getHeight());
}
@Test
@Disabled("Flakey test needs investigating")
void whenDisabled_thenSkips() {
assertEquals(999, display.getHeight());
}
@Test
void whenAssumptionsFail_thenAborts() {
assumeTrue(display.getPlatform() == Platform.MOBILE, "test only runs for mobile");
}
}
這裡我們提供了一組包含四個測試的測試案例。第一個測試案例會成功,因為我們設定的height正確。第二個測試用例會失敗,因為我們設定的height錯誤。第三個測試案例會被跳過,因為它被標記為@Disabled 。最後,第四個測試案例會中止,因為它應該只針對行動Displays運行,而被測Display是桌面顯示器。
3. 驗證測試引擎
引擎測試工具包讓我們可以使用自己選擇的測試引擎。 JUnit 5 的預設測試引擎是junit-jupiter 。不過,我們也可以編寫自己的測試引擎,或使用其他引擎,例如junit-vintage ,它非常適合運行舊版的 JUnit。
開始測試的一個好方法是確認我們能夠找到想要使用的測試引擎。然後,我們還可以檢查測試引擎是否能夠識別我們的測試計劃。讓我們寫一個測驗來完成這兩項任務:
@Test
void givenJunitJupiterEngine_whenRunningTestSuite_thenTestsAreDiscovered() {
EngineDiscoveryResults results = EngineTestKit.engine("junit-jupiter")
.selectors(selectClass(DisplayTest.class))
.discover();
assertEquals(emptyList(), results.getDiscoveryIssues());
}
在這個測試中,我們首先指定了要使用的測試引擎名稱「 junit-jupiter 」。然後傳入了測試類,最後呼叫了discover().最後一行的斷言確認了發現過程沒有出現任何問題。檢查此處出現的任何問題,是調試出錯原因的好方法。
4. 收集高階測試統計數據
現在我們已經有了測試計劃,並且驗證了我們選擇的測試引擎可用且能夠檢測到我們的測試。是時候運行測試並收集一些高級統計資料了:
@Test
void givenTestSuite_whenRunningAllTests_thenCollectHighLevelStats() {
EngineTestKit
.engine("junit-jupiter")
.selectors(selectClass(DisplayTest.class))
.execute()
.testEvents()
.assertStatistics(stats ->
stats.started(3).finished(3).succeeded(1).failed(1).skipped(1).aborted(1));
}
本次測試的開始方式與上一次類似;我們指定測試引擎和測試類別。完成設定後,我們呼叫execute()函數來執行測試。運行結束後,我們斷言所有預期統計資料。這裡我們可以看到,正如預期,我們得到了一個成功實例、一個失敗實例、一個跳過實例和一個中止實例。
我們還可以檢查其他統計數據。例如, dynamicallyRegistered()可以檢查測試計畫執行期間發生的dynamic registration事件的數量。
5. 收集測試特定事件
接下來,我們來看看如何更深入分析測試計劃的結果。
5.1. 核實中止測試的原因
我們知道預期會有一個測試中止。之前,我們可以斷言至少有一個測試中止了。然而,至關重要的是要了解測試是否正確中止,以及中止的原因是否符合預期。我們可以使用引擎測試工具包,透過收集測試運行中的Events來確認這一點:
Events testEvents = EngineTestKit
.engine("junit-jupiter")
.selectors(selectMethod(DisplayTest.class, "aborts"))
.execute()
.testEvents();
這段程式碼中,我們像往常一樣指定了測試引擎。然後,我們從DisplayTest類別中選擇了要查看的特定方法aborts() 。最後,我們運行測試並請求返回Events 。收集到事件後,我們現在可以檢查是否發生了中止,以及中止原因是否符合預期:
testEvents.assertThatEvents()
.haveExactly(1, event(test("aborts"),
abortedWithReason(instanceOf(TestAbortedException.class),
message(message -> message.contains("test only runs for mobile")))));
在本測試部分,我們斷言三件事。首先,我們檢查是否只有一個事件,因為我們預期只執行一個測試;這有效地驗證了我們的設定是否正確。然後,我們使用abortedWithReason()來檢查是否確實中止了測試,以及傳回的訊息是否符合預期;該測試僅在行動裝置顯示器上執行。
5.2. 驗證測試失敗原因
讓我們來看看如何驗證測試是否如預期般失敗,以及失敗原因是否與我們預期一致。首先,像之前一樣,我們選擇一個測試引擎,選擇我們的fails()測試,並收集Events :
Events testEvents = EngineTestKit
.engine("junit-jupiter")
.selectors(selectMethod(DisplayTest.class, "fails"))
.execute()
.testEvents();
這次,我們將檢查兩件事:首先,確保每個測試只有一個Event 。其次,我們將使用finishedWithFailure()方法來檢查測試是否如預期般失敗,以及導致失敗的錯誤是否正確:
testEvents.assertThatEvents()
.haveExactly(1, event(test("fails"),
finishedWithFailure(instanceOf(AssertionFailedError.class))));
透過這些斷言,我們可以確信正確的測試會因為正確的原因而失敗。當然,我們也可以在這裡檢查任何類型的Error或Exception 。
除了我們在這裡使用的abortedWithReason()和finishedWithFailure()方法之外,還有一整套方法來斷言測試是否按預期運行。例如skippedWithReason(), finishedSuccessfully()和finishedWithCause() 。
6. 結論
在本教學中,我們了解如何使用引擎測試工具包執行一系列測試。我們追蹤了一些高級統計信息,例如運行的測試數量,並統計了通過、失敗、跳過和中止的測試數量。然而,我們還可以追蹤其他一系列測試結果。
然後我們更深入地編寫了測試,以驗證測試中止或失敗的原因。這有助於了解情況是否發生變化,以及是否出現了新的失敗原因。
與往常一樣,範例的完整程式碼可在 GitHub 上找到。