Parasoft:談?wù)勥w移到Junit 5以獲取最新技術(shù)的好處
自JUnit 5發(fā)行以來(lái)已經(jīng)有幾年了。如果您尚未開(kāi)始將其用于開(kāi)發(fā)測(cè)試,則應(yīng)該這樣做。 JUnit 5具有許多新功能和改進(jìn)功能,可以節(jié)省您的時(shí)間和麻煩。讓我們看一下如何開(kāi)始使用JUnit 5以獲得最新技術(shù)的好處。
從JUnit 4遷移到JUnit 5的原因
如果您使用JUnit 4已有一段時(shí)間,那么遷移測(cè)試似乎是一項(xiàng)艱巨的任務(wù)。好消息是您可能不需要轉(zhuǎn)換任何測(cè)試——JUnit 5可以使用Vintage庫(kù)運(yùn)行JUnit 4測(cè)試,因此您可以開(kāi)始使用JUnit 5編寫(xiě)新的測(cè)試。
這是開(kāi)始使用JUnit 5的四個(gè)基本理由:
- JUnit 5利用了Java 8或更高版本的功能(例如lambda函數(shù)),使測(cè)試更強(qiáng)大且更易于維護(hù)。
- JUnit 5添加了一些非常有用的新功能,用于描述、組織和執(zhí)行測(cè)試。例如,測(cè)試可以獲得更好的顯示名稱(chēng),并且可以按層次進(jìn)行組織。
- JUnit 5被組織為多個(gè)庫(kù),因此僅將您需要的功能導(dǎo)入到項(xiàng)目中。使用Maven和Gradle之類(lèi)的構(gòu)建系統(tǒng),包含正確的庫(kù)很容易。
- JUnit 5一次只能使用一個(gè)以上的擴(kuò)展,而JUnit 4則不能(一次只能使用一個(gè)運(yùn)行程序)。這意味著您可以輕松地將Spring擴(kuò)展與其他擴(kuò)展(例如您自己的自定義擴(kuò)展)結(jié)合在一起。
如何遷移到JUnit 5
即使您已有現(xiàn)有的JUnit 4測(cè)試,從JUnit 4切換到JUnit 5也非常簡(jiǎn)單。除非需要新功能,否則大多數(shù)組織不需要將舊的JUnit轉(zhuǎn)換為JUnit 5。
- 將您的庫(kù)和構(gòu)建系統(tǒng)從JUnit 4更新到JUnit5。請(qǐng)確保在測(cè)試運(yùn)行時(shí)路徑中包括JUnit-vintage-engine工件,以允許執(zhí)行現(xiàn)有測(cè)試。
- 開(kāi)始使用新的JUnit 5構(gòu)造構(gòu)建新的測(cè)試。
- (可選)將JUnit 3和JUnit 4測(cè)試轉(zhuǎn)換為JUnit 5。
JUnit 5和JUnit 4之間的重要區(qū)別
JUnit 5測(cè)試看起來(lái)與JUnit 4幾乎相同,但是您應(yīng)該注意一些差異。
輸入
JUnit 5將新的org.JUnit.jupiter包用于其注釋和類(lèi)。例如,org.JUnit.Test成為org.JUnit.jupiter.api.Test。
注解
@Test注釋不再具有參數(shù);這些都已移至某個(gè)功能。例如,要指示期望測(cè)試在JUnit 4中引發(fā)異常:
在JUnit 5中,它已更改為:
同樣,超時(shí)也已更改。在JUnit 4中,它們?nèi)缦滤荆?/span>
在JUnit 5中,超時(shí)如下所示:
以下是其他已更改的注釋?zhuān)?
- @Before已成為@BeforeEach
- @After已成為@AfterEach
- @BeforeClass已變?yōu)?/span>@BeforeAll
- @AfterClass已成為@AfterAll
- @Ignore已成為@Disabled
- @Category已成為@Tag
- @Rule和@ClassRule不見(jiàn)了——改用@ExtendWith和@RegisterExtension
斷言類(lèi)
JUnit 5斷言類(lèi)現(xiàn)在位于org.JUnit.jupiter.api.Assertions中。大多數(shù)常見(jiàn)的斷言類(lèi),例如assertEquals()和assertNotNull()看起來(lái)都與以前相同,但是有一些關(guān)鍵的區(qū)別:
- 錯(cuò)誤消息現(xiàn)在是最后一個(gè)參數(shù),例如:assertEquals(“my message”, 1, 2) 將是assertEquals(1, 2, “my message”)
- 現(xiàn)在,大多數(shù)斷言都接受構(gòu)造錯(cuò)誤消息的lambda,僅在斷言失敗時(shí)才調(diào)用該消息。
- assertTimeout()和assertTimeoutPreemptively()已替換@Timeout批注(請(qǐng)注意,JUnit 5中有一個(gè)@Timeout批注,但其工作原理不同于JUnit 4)。
- 有幾個(gè)新的斷言,如下所述。
請(qǐng)注意,如果愿意,您可以在JUnit 5測(cè)試中繼續(xù)使用來(lái)自JUnit 4的斷言。
假設(shè)條件
假設(shè)已移至org.JUnit.jupiter.api.Assumptions。
存在相同的假設(shè),但現(xiàn)在支持BooleanSupplier以及Hamcrest匹配器以匹配條件。滿足條件時(shí),可以使用Lambda(類(lèi)型為Executable)來(lái)執(zhí)行代碼。
這是JUnit 4中的示例:
在JUnit 5中,它變?yōu)椋?/span>
擴(kuò)展JUnit
在JUnit 4中,自定義框架通常意味著使用@RunWith批注指定自定義運(yùn)行器。使用多個(gè)運(yùn)行程序是有問(wèn)題的,通常需要鏈接或使用@Rule。使用擴(kuò)展在JUnit 5中對(duì)此進(jìn)行了簡(jiǎn)化和改進(jìn)。
例如,在JUnit 4中使用Spring框架構(gòu)建測(cè)試如下所示:
使用JUnit 5,您可以改為包含Spring Extension:
@ExtendWith注釋是可重復(fù)的,這意味著可以輕松組合多個(gè)擴(kuò)展名。
您還可以通過(guò)創(chuàng)建一個(gè)實(shí)現(xiàn)org.JUnit.jupiter.api.extension中的一個(gè)或多個(gè)接口的類(lèi),然后使用@ExtendWith將其添加到我們的測(cè)試中,來(lái)輕松定義我們自己的自定義擴(kuò)展。
將測(cè)試轉(zhuǎn)換為JUnit 5
要將現(xiàn)有的JUnit 3或JUnit 4測(cè)試轉(zhuǎn)換為JUnit 5,以下步驟應(yīng)適用于大多數(shù)測(cè)試:
- 更新導(dǎo)入以刪除JUnit 4并添加JUnit5。例如,更新@Test批注的程序包名稱(chēng),以及斷言的程序包和類(lèi)名(從斷言到斷言)。如果有編譯錯(cuò)誤,請(qǐng)不要擔(dān)心,完成以下步驟即可解決這些錯(cuò)誤。
- 用新的全局替換舊的注釋和類(lèi)名。例如,將所有@Before替換為@BeforeEach,并將所有Asserts替換為Assertions。
- 更新斷言。提供消息的任何斷言都需要將message參數(shù)移到末尾。當(dāng)所有三個(gè)參數(shù)都是字符串時(shí),請(qǐng)?zhí)貏e注意!另外,更新超時(shí)和預(yù)期的異常(請(qǐng)參閱上面的示例)。
- 如果您要使用假設(shè),請(qǐng)進(jìn)行更新。
- 用適當(dāng)?shù)?/span>@ExtendWith注釋替換@ RunWith,@ Rule或@ClassRule的所有實(shí)例。您可能需要在線獲取有關(guān)示例擴(kuò)展的更新文檔。
請(qǐng)注意,遷移參數(shù)化測(cè)試將需要更多的重構(gòu),尤其是如果您一直在使用JUnit 4參數(shù)化(JUnit 5參數(shù)化測(cè)試的格式更接近JUnitParams)。
新功能
到目前為止,我僅討論了現(xiàn)有功能及其更改方式。但是JUnit 5提供了許多新功能,使我們的測(cè)試更具描述性和可維護(hù)性。
顯示名稱(chēng)
使用JUnit 5,可以將@DisplayName批注添加到類(lèi)和方法。生成報(bào)告時(shí)使用該名稱(chēng),這使描述測(cè)試的目的以及跟蹤故障更加容易,例如:
您還可以使用顯示名稱(chēng)生成器來(lái)處理您的測(cè)試類(lèi)和/或方法以生成您喜歡的任何格式的測(cè)試名稱(chēng)。有關(guān)詳細(xì)信息和示例,請(qǐng)參見(jiàn)JUnit文檔。
斷言
JUnit 5引入了一些新的斷言,例如:
- assertIterableEquals()使用equals()對(duì)兩個(gè)可迭代對(duì)象進(jìn)行深入驗(yàn)證
- assertLinesMatch()驗(yàn)證兩個(gè)字符串列表是否匹配;它在“expected”參數(shù)中接受正則表達(dá)式。
- assertAll()將多個(gè)斷言組合在一起。額外的好處是,即使單個(gè)斷言失敗,也將執(zhí)行所有斷言。
- assertThrows()和assertDoesNotThrow()已替換@Test批注中的預(yù)期屬性
嵌套測(cè)試
JUnit 4中的測(cè)試套件很有用,但是JUnit 5中的嵌套測(cè)試更易于設(shè)置和維護(hù),它們可以更好地描述測(cè)試組之間的關(guān)系,例如:
在上面的示例中,您可以看到我對(duì)與MyClass相關(guān)的所有測(cè)試使用了單個(gè)類(lèi)。我可以驗(yàn)證該類(lèi)在外部測(cè)試類(lèi)中是否可實(shí)例化,并且我對(duì)所有實(shí)例化和初始化MyClass的測(cè)試使用嵌套的內(nèi)部類(lèi)。@BeforeEach方法僅適用于嵌套類(lèi)中的測(cè)試。
測(cè)試和類(lèi)的@DisplayNames批注指示測(cè)試的目的和組織。這有助于了解測(cè)試報(bào)告,因?yàn)槟梢钥吹綀?zhí)行測(cè)試的條件(使用初始化驗(yàn)證MyClass)以及測(cè)試正在驗(yàn)證的內(nèi)容(myMethod返回true)。這是用于JUnit 5的良好測(cè)試設(shè)計(jì)模式。
參數(shù)化測(cè)試
JUnit 4中使用內(nèi)置庫(kù)(例如JUnit4Parameterized)或第三方庫(kù)(例如JUnitParams)進(jìn)行測(cè)試參數(shù)化。在JUnit 5中,參數(shù)化測(cè)試是完全內(nèi)置的,并采用了JUnit4Parameterized和JUnitParams的一些最佳功能,例如:
格式類(lèi)似于JUnitParams,其中參數(shù)直接傳遞到測(cè)試方法。請(qǐng)注意,要測(cè)試的值可以來(lái)自幾個(gè)不同的來(lái)源。在這里,我只有一個(gè)參數(shù),因此使用@ValueSource很容易。@EmptySource和@NullSource表示我想分別向運(yùn)行的值列表添加一個(gè)空字符串和一個(gè)null(如果同時(shí)使用它們,則可以如上所述將它們組合在一起)。還有多個(gè)其他值源,例如@EnumSource和@ArgumentsSource(自定義值提供程序)。如果需要多個(gè)參數(shù),則也可以使用@MethodSource或@CsvSource。有關(guān)更多詳細(xì)信息和示例,請(qǐng)參見(jiàn)JUnit 5文檔。
JUnit 5中添加的另一種測(cè)試類(lèi)型是@RepeatedTest,其中將單個(gè)測(cè)試重復(fù)指定的次數(shù)。
有條件的測(cè)試執(zhí)行
JUnit 5提供了ExecutionCondition擴(kuò)展API,以有條件地啟用或禁用測(cè)試或容器(測(cè)試類(lèi))。這就像在測(cè)試中使用@Disabled一樣,但是它可以定義自定義條件。有多個(gè)內(nèi)置條件,例如:
- @EnabledOnOs和@DisabledOnOs:僅在指定的操作系統(tǒng)上啟用測(cè)試。
- @EnabledOnJre和@DisabledOnJre:指定應(yīng)該為特定版本的Java啟用或禁用測(cè)試。
- @EnabledIfSystemProperty:基于JVM系統(tǒng)屬性的值啟用測(cè)試。
- @EnabledIf:如果符合腳本條件,則使用腳本邏輯來(lái)啟用測(cè)試。
測(cè)試模板
測(cè)試模板不是常規(guī)測(cè)試。它們定義了一組要執(zhí)行的步驟,然后可以使用特定的調(diào)用上下文在其他位置執(zhí)行這些步驟。這意味著您可以一次定義一個(gè)測(cè)試模板,然后在運(yùn)行時(shí)構(gòu)建一個(gè)調(diào)用上下文列表以運(yùn)行該測(cè)試。在Junit 5文檔中找到更多詳細(xì)信息和示例。
動(dòng)態(tài)測(cè)試
動(dòng)態(tài)測(cè)試就像測(cè)試模板一樣,要運(yùn)行的測(cè)試是在運(yùn)行時(shí)生成的。但是,雖然測(cè)試模板是通過(guò)一組特定的步驟定義的并且可以多次運(yùn)行,但是動(dòng)態(tài)測(cè)試使用相同的調(diào)用上下文,但是可以執(zhí)行不同的邏輯。動(dòng)態(tài)測(cè)試的一種用途是流式傳輸抽象對(duì)象列表,并根據(jù)其具體類(lèi)型對(duì)每個(gè)對(duì)象執(zhí)行一組獨(dú)立的斷言。有關(guān)良好的示例,請(qǐng)參見(jiàn)Junit 5文檔。
結(jié)論
JUnit 5是對(duì)JUnit框架的強(qiáng)大而靈活的更新。它提供了各種改進(jìn)和新功能來(lái)組織和描述測(cè)試用例,并有助于理解測(cè)試結(jié)果。更新JUnit 5既快速又容易——只需更新項(xiàng)目依賴項(xiàng)并開(kāi)始使用新功能。