原創|使用教程|編輯:鄭恭琳|2020-12-07 11:29:15.390|閱讀 337 次
概述:參數化測試是定義和運行多個測試用例的好方法,它們之間的唯一區別是數據。在這里,我們看一下JUnit測試常用的三個不同框架。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
參數化測試是定義和運行多個測試用例的好方法,它們之間的唯一區別是數據。在這里,我們看一下JUnit測試常用的三個不同框架。
在編寫單元測試時,通常會在測試方法本身中初始化方法輸入參數和預期結果。在某些情況下,使用少量輸入就足夠了;但是,在某些情況下,我們需要使用大量的值來驗證代碼中的所有功能。參數化測試是定義和運行多個測試用例的好方法,它們之間的唯一區別是數據。他們可以驗證各種值的代碼行為,包括邊界情況。參數化測試可以增加代碼覆蓋率,并確保代碼按預期運行。
有許多用于Java的良好參數化框架。在本文中,我們將研究JUnit測試常用的三個不同框架,并將它們與每個測試的結構示例進行比較。最后,我們將探索如何簡化和加速參數化測試的創建。
讓我們比較一下三種最常見的框架:JUnit 4,JunitParams和JUnit5。每個JUnit參數化框架都有自己的優點和缺點。
JUnit 4
優點:
缺點:
JunitParams
優點:
缺點:
JUnit 5
優點:
缺點:
例如,假設我們有一種處理銀行貸款請求的方法。我們可能會編寫一個單元測試,以指定貸款請求金額、預付定金金額和其他值。然后,我們將創建斷言來驗證響應——貸款可以被批準或拒絕,并且響應可以指定貸款的條款。
例如:
public LoanResponse requestLoan(float loanAmount, float downPayment, float availableFunds) { LoanResponse response = new LoanResponse(); response.setApproved(true); if (availableFunds < downPayment) { response.setApproved(false); response.setMessage(“error.insufficient.funds.for.down.payment“); return response; } if (downPayment / loanAmount < 0.1) { response.setApproved(false); response.setMessage(“error.insufficient.down.payment“); } return response; }
首先,讓我們看一下上述方法的常規測試:
@Test public void testRequestLoan() throws Throwable { // Given LoanProcessor underTest = new LoanProcessor(); // When LoanResponse result = underTest.requestLoan(1000f, 200f, 250f); // Then assertNotNull(result); assertTrue(result.isApproved()); assertNull(result.getMessage()); }
在此示例中,我們通過請求1000美元的貸款,200美元的首付并指示請求者有250美元的可用資金來測試我們的方法。然后,測試將驗證貸款是否已獲批準,并且未在響應中提供任何信息。
為了確保對我們的requestLoan()方法進行了徹底的測試,我們需要使用各種預付款,請求的貸款金額和可用資金進行測試。例如,讓我們測試一筆零首付的100萬美元貸款請求,該請求應被拒絕。我們可以簡單地用不同的值復制現有測試,但是由于測試邏輯相同,因此參數化測試效率更高。
我們將參數化請求的貸款金額,預付款和可用資金以及預期的結果:貸款是否被批準,以及在驗證后返回的消息。每組請求數據及其預期結果將成為其自己的測試用例。
讓我們從一個Junit 4 Parameterized示例開始。要創建參數化測試,我們首先需要定義測試的變量。我們還需要包括一個構造函數來初始化它們:
@RunWith(Parameterized.class) public class LoanProcessorParameterizedTest { float loanAmount; float downPayment; float availableFunds; boolean expectApproved; String expectedMessage; public LoanProcessorParameterizedTest(float loanAmount, float downPayment, float availableFunds, boolean expectApproved, String expectedMessage) { this.loanAmount = loanAmount; this.downPayment = downPayment; this.availableFunds = availableFunds; this.expectApproved = expectApproved; this.expectedMessage = expectedMessage; } // … }
在這里,我們看到該測試使用@RunWith批注指定該測試將與Junit4參數化運行器一起運行。 該跑步者知道正在尋找一種方法,該方法將為測試提供值集(用@Parameters注釋),正確初始化測試并運行多行測試。
請注意,每個參數都在測試類中定義為一個字段,并且構造函數初始化這些值(如果您不想創建構造函數,也可以使用@Parameter注釋將值注入字段)。對于值集中的每一行,參數化運行器將實例化測試類并運行該類中的每個測試。
讓我們添加一個為參數化運行器提供參數的方法:
@Parameters(name = “Run {index}: loanAmount={0}, downPayment={1}, availableFunds={2}, expectApproved={3}, expectedMessage={4}“) public static Iterable<Object[]> data() throws Throwable { return Arrays.asList(new Object[][] { { 1000.0f, 200.0f, 250.0f, true, null } }); }
值集通過data()方法構建為“對象數組列表”,并使用@Parameters進行注釋。請注意,@ Parameters使用占位符設置測試的名稱,將在運行測試時將其替換。稍后我們將看到,這使得查看測試結果中的值更加容易。當前,只有一行數據用于測試應批準貸款的情況。我們可以添加更多行以增加被測方法的覆蓋范圍。
@Parameters(name = “Run {index}: loanAmount={0}, downPayment={1}, availableFunds={2}, expectApproved={3}, expectedMessage={4}“) public static Iterable<Object[]> data() throws Throwable { return Arrays.asList(new Object[][] { { 1000.0f, 200.0f, 250.0f, true, null }, { 1000.0f, 50.0f, 250.0f, false, “error.insufficient.down.payment“ }, { 1000.0f, 200.0f, 150.0f, false, “error.insufficient.funds.for.down.payment“ } }); }
在這里,我們有一個測試案例,其中貸款將被批準,而另外兩個案例中,由于不同的原因而不應被批準。我們可能要添加使用零或負值的行以及測試邊界條件。
現在我們準備創建測試方法:
@Test public void testRequestLoan() throws Throwable { // Given LoanProcessor underTest = new LoanProcessor(); // When LoanResponse result = underTest.requestLoan(loanAmount, downPayment, availableFunds); // Then assertNotNull(result); assertEquals(expectApproved, result.isApproved()); assertEquals(expectedMessage, result.getMessage()); }
在這里,我們在調用requestLoan()方法并驗證結果時引用這些字段。
JunitParams庫通過允許將參數直接傳遞給測試方法來簡化參數化測試語法。參數值由單獨的方法提供,其名稱在@Parameters批注中引用。
@RunWith(JUnitParamsRunner.class) public class LoanProcessorParameterizedTest2 { @Test @Parameters(method = “testRequestLoan_Parameters“) public void testRequestLoan(float loanAmount, float downPayment, float availableFunds, boolean expectApproved, String expectedMessage) throws Throwable { … } @SuppressWarnings(“unused“) private static Object[][] testRequestLoan_Parameters() throws Throwable { // Parameters: loanAmount={0}, downPayment={1}, availableFunds={2}, expectApproved={3}, expectedMessage={4} return new Object[][] { { 1000.0f, 200.0f, 250.0f, true, null }, { 1000.0f, 50.0f, 250.0f, false, “error.insufficient.down.payment“}, { 1000.0f, 200.0f, 150.0f, false, “error.insufficient.funds.for.down.payment“ } }; } }
JunitParams的另一個好處是,除了在代碼中提供值外,它還支持使用CSV文件提供值。這允許將測試與數據分離,并在不更新代碼的情況下更新數據值。
JUnit 5解決了JUnit 4的一些局限和缺點。與JunitParams一樣,Junit 5也簡化了參數化測試的語法。語法上最重要的變化是:
在Junit 5中定義相同的示例如下所示:
public class LoanProcessorParameterizedTest { @ParameterizedTest(name=“Run {index}: loanAmount={0}, downPayment={1}, availableFunds={2}, expectApproved={3}, expectedMessage={4}“) @MethodSource(“testRequestLoan_Parameters“) public void testRequestLoan(float loanAmount, float downPayment, float availableFunds, boolean expectApproved, String expectedMessage) throws Throwable { … } static Stream<Arguments> testRequestLoan_Parameters() throws Throwable { return Stream.of( Arguments.of(1000.0f, 200.0f, 250.0f, true, null), Arguments.of(1000.0f, 50.0f, 250.0f, false, “error.insufficient.down.payment“), Arguments.of(1000.0f, 200.0f, 150.0f, false, “error.insufficient.funds.for.down.payment“) ); } }
可以想象,編寫上面的參數化測試可能會有些麻煩。對于每個參數化的測試框架,都需要正確編寫一些樣板代碼。記住正確的結構可能很困難,而且要花時間寫出來。為了使此操作更容易,您可以使用Parasoft Jtest自動生成參數化測試,就像上面描述的那樣。為此,只需選擇要為其生成測試的方法(在Eclipse或IntelliJ中),即可:
使用默認值和斷言生成測試。然后,您可以使用實際輸入值和斷言配置測試,并將更多數據行添加到data()方法。
Parasoft Jtest可以直接在Eclipse和IntelliJ中運行參數化測試。
Eclipse中的JUnit視圖
請注意,如圖所示,每個測試的名稱都包含來自數據集的輸入值和預期結果值。由于在每種情況下都會顯示輸入參數和預期的輸出,因此可以使測試失敗時的調試更加容易。
您還可以使用Parasoft Jtest的“全部運行”操作:
Parasoft Jtest中的“流樹”視圖
它分析測試流程并提供有關先前測試運行的詳細信息。 這使您可以查看測試中發生的情況,而無需使用斷點或調試語句重新運行測試。例如,您可以在“變量”視圖中看到參數化的值:
Parasoft Jtest中的變量視圖
我們審查的三個框架中的每一個都是不錯的選擇,并且運作良好。如果使用JUnit 4,則由于測試類的設計更加簡潔,并且能夠在同一類中定義多個測試方法,因此我傾向于使用JunitParams而不是內置的JUnit 4 Parameterized框架。但是,如果使用JUnit 5,我建議您使用內置的JUnit 5框架,因為它可以解決JUnit 4中的缺點,并且不需要額外的庫。我還喜歡使用Parasoft Jtest的單元測試功能來提高參數化測試的創建、執行和調試的效率。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn