日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
JUnit:別再用 main 方法測試了,好嗎?

01、前世今生

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、小程序開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了寧津免費建站歡迎大家使用!

你好呀,我是 JUnit,一個開源的 Java 單元測試框架。在了解我之前,先來了解一下什么是單元測試。單元測試,就是針對最小的功能單元編寫測試代碼。在 Java 中,最小的功能單元就是方法,因此,對 Java 程序員進行單元測試實際上就是對 Java 方法的測試。

為什么要進行單元測試呢?因為單元測試可以確保你編寫的代碼是符合軟件需求和遵循開發(fā)規(guī)范的。單元測試是所有測試中最底層的一類測試,是第一個環(huán)節(jié),也是最重要的一個環(huán)節(jié),是唯一一次能夠達到代碼覆蓋率 100% 的測試,是整個軟件測試過程的基礎(chǔ)和前提??梢赃@么說,單元測試的性價比是最好的。

微軟公司之前有這樣一個統(tǒng)計:bug 在單元測試階段被發(fā)現(xiàn)的平均耗時是 3.25 小時,如果遺漏到系統(tǒng)測試則需要 11.5 個小時。

經(jīng)我這么一說,你應(yīng)該已經(jīng)很清楚單元測試的重要性了。那在你最初編寫測試代碼的時候,是不是經(jīng)常這么做?就像下面這樣。

 
 
 
 
  1. public class Factorial { 
  2.     public static long fact(long n) { 
  3.         long r = 1; 
  4.         for (long i = 1; i <= n; i++) { 
  5.             r = r * i; 
  6.         } 
  7.         return r; 
  8.     } 
  9.  
  10.     public static void main(String[] args) { 
  11.         if (fact(3) == 6) { 
  12.             System.out.println("通過"); 
  13.         } else { 
  14.             System.out.println("失敗"); 
  15.         } 
  16.     } 

要測試 fact() 方法正確性,你在 main() 方法中編寫了一段測試代碼。如果你這么做過的話,我只能說你也曾經(jīng)青澀天真過啊!使用 main() 方法來測試有很多壞處,比如說:

1)測試代碼沒有和源代碼分開。

2)不夠靈活,很難編寫一組通用的測試代碼。

3)無法自動打印出預(yù)期和實際的結(jié)果,沒辦法比對。

但如果學(xué)會使用我——JUnit 的話,就不會再有這種困擾了。我可以非常簡單地組織測試代碼,并隨時運行它們,還能給出準確的測試報告,讓你在最短的時間內(nèi)發(fā)現(xiàn)自己編寫的代碼到底哪里出了問題。

02、上手指南

好了,既然知道了我這么優(yōu)秀,那還等什么,直接上手吧!我最新的版本是 JUnit 5,Intellij IDEA 中已經(jīng)集成了,所以你可以直接在 IDEA 中編寫并運行我的測試用例。

第一步,直接在當前的代碼編輯器窗口中按下 Command+N 鍵(Mac 版),在彈出的菜單中選擇「Test...」。

勾選上要編寫測試用例的方法 fact(),然后點擊「OK」。

此時,IDEA 會自動在當前類所在的包下生成一個類名帶 Test(慣例)的測試類。如下圖所示。

如果你是第一次使用我的話,IDEA 會提示你導(dǎo)入我的依賴包。建議你選擇最新的 JUnit 5.4。

導(dǎo)入完畢后,你可以打開 pom.xml 文件確認一下,里面多了對我的依賴。

 
 
 
 
  1.  
  2.     org.junit.jupiter 
  3.     junit-jupiter 
  4.     RELEASE 
  5.     compile 
  6.  

第二步,在測試方法中添加一組斷言,如下所示。

 
 
 
 
  1. @Test 
  2. void fact() { 
  3.     assertEquals(1, Factorial.fact(1)); 
  4.     assertEquals(2, Factorial.fact(2)); 
  5.     assertEquals(6, Factorial.fact(3)); 
  6.     assertEquals(100, Factorial.fact(5)); 

@Test 注解是我要求的,我會把帶有 @Test 的方法識別為測試方法。在測試方法內(nèi)部,你可以使用 assertEquals() 對期望的值和實際的值進行比對。

第三步,你可以在郵件菜單中選擇「Run FactorialTest」來運行測試用例,結(jié)果如下所示。

測試失敗了,因為第 20 行的預(yù)期結(jié)果和實際不符,預(yù)期是 100,實際是 120。此時,你要么修正實現(xiàn)代碼,要么修正測試代碼,直到測試通過為止。

不難吧?單元測試可以確保單個方法按照正確的預(yù)期運行,如果你修改了某個方法的代碼,只需確保其對應(yīng)的單元測試通過,即可認為改動是沒有問題的。

03、瞻前顧后

在一個測試用例中,可能要對多個方法進行測試。在測試之前呢,需要準備一些條件,比如說創(chuàng)建對象;在測試完成后呢,需要把這些對象銷毀掉以釋放資源。如果在多個測試方法中重復(fù)這些樣板代碼又會顯得非常啰嗦。

這時候,該怎么辦呢?

我為你提供了 setUp() 和 tearDown(),作為一個文化人,我稱之為“瞻前顧后”。來看要測試的代碼。

 
 
 
 
  1. public class Calculator { 
  2.     public int sub(int a, int b) { 
  3.         return a - b; 
  4.     } 
  5.     public int add(int a, int b) { 
  6.         return a + b; 
  7.     } 

新建測試用例的時候記得勾選setUp 和 tearDown。

生成后的代碼如下所示。

 
 
 
 
  1. class CalculatorTest { 
  2.     Calculator calculator; 
  3.  
  4.     @BeforeEach 
  5.     void setUp() { 
  6.         calculator = new Calculator(); 
  7.     } 
  8.  
  9.     @AfterEach 
  10.     void tearDown() { 
  11.         calculator = null; 
  12.     } 
  13.  
  14.  
  15.     @Test 
  16.     void sub() { 
  17.         assertEquals(0,calculator.sub(1,1)); 
  18.     } 
  19.  
  20.     @Test 
  21.     void add() { 
  22.         assertEquals(2,calculator.add(1,1)); 
  23.     } 

@BeforeEach 的 setUp() 方法會在運行每個 @Test 方法之前運行;@AfterEach 的tearDown() 方法會在運行每個 @Test 方法之后運行。

與之對應(yīng)的還有 @BeforeAll 和 @AfterAll,與 @BeforeEach 和 @AfterEach 不同的是,All 通常用來初始化和銷毀靜態(tài)變量。

 
 
 
 
  1. public class DatabaseTest { 
  2.     static Database db; 
  3.  
  4.     @BeforeAll 
  5.     public static void init() { 
  6.         db = createDb(...); 
  7.     } 
  8.      
  9.     @AfterAll 
  10.     public static void drop() { 
  11.         ... 
  12.     } 

03、異常測試

對于 Java 程序來說,異常處理也非常的重要。對于可能拋出的異常進行測試,本身也是測試的一個重要環(huán)節(jié)。

還拿之前的 Factorial 類來進行說明。在 fact() 方法的一開始,對參數(shù) n 進行了校驗,如果小于 0,則拋出 IllegalArgumentException 異常。

 
 
 
 
  1. public class Factorial { 
  2.     public static long fact(long n) { 
  3.         if (n < 0) { 
  4.             throw new IllegalArgumentException("參數(shù)不能小于 0"); 
  5.         } 
  6.         long r = 1; 
  7.         for (long i = 1; i <= n; i++) { 
  8.             r = r * i; 
  9.         } 
  10.         return r; 
  11.     } 

在 FactorialTest 中追加一個測試方法 factIllegalArgument()。

 
 
 
 
  1. @Test 
  2. void factIllegalArgument() { 
  3.     assertThrows(IllegalArgumentException.class, new Executable() { 
  4.         @Override 
  5.         public void execute() throws Throwable { 
  6.             Factorial.fact(-2); 
  7.         } 
  8.     }); 

我為你提供了一個 assertThrows() 的方法,第一個參數(shù)是異常的類型,第二個參數(shù) Executable,可以封裝產(chǎn)生異常的代碼。如果覺得匿名內(nèi)部類寫起來比較復(fù)雜的話,可以使用 Lambda 表達式。

 
 
 
 
  1. @Test 
  2. void factIllegalArgumentLambda() { 
  3.     assertThrows(IllegalArgumentException.class, () -> { 
  4.         Factorial.fact(-2); 
  5.     }); 

04、忽略測試

有時候,由于某些原因,某些方法產(chǎn)生了 bug,需要一段時間去修復(fù),在修復(fù)之前,該方法對應(yīng)的測試用例一直是以失敗告終的,為了避免這種情況,我為你提供了 @Disabled 注解。

 
 
 
 
  1. class DisabledTestsDemo { 
  2.  
  3.     @Disabled("該測試用例不再執(zhí)行,直到編號為 43 的 bug 修復(fù)掉") 
  4.     @Test 
  5.     void testWillBeSkipped() { 
  6.     } 
  7.  
  8.     @Test 
  9.     void testWillBeExecuted() { 
  10.     } 
  11.  

@Disabled 注解也可以不需要說明,但我建議你還是提供一下,簡單地說明一下為什么這個測試方法要忽略。在上例中,如果團隊的其他成員看到說明就會明白,當編號 43 的 bug 修復(fù)后,該測試方法會重新啟用的。即便是為了提醒自己,也很有必要,因為時間長了你可能自己就忘了,當初是為什么要忽略這個測試方法的。

05、條件測試

有時候,你可能需要在某些條件下運行測試方法,有些條件下不運行測試方法。針對這場使用場景,我為你提供了條件測試。

1)不同的操作系統(tǒng),可能需要不同的測試用例,比如說 Linux 和 Windows 的路徑名是不一樣的,通過 @EnabledOnOs 注解就可以針對不同的操作系統(tǒng)啟用不同的測試用例。

 
 
 
 
  1. @Test 
  2. @EnabledOnOs(MAC) 
  3. void onlyOnMacOs() { 
  4.     // ... 
  5.  
  6. @TestOnMac 
  7. void testOnMac() { 
  8.     // ... 
  9.  
  10. @Test 
  11. @EnabledOnOs({ LINUX, MAC }) 
  12. void onLinuxOrMac() { 
  13.     // ... 
  14.  
  15. @Test 
  16. @DisabledOnOs(WINDOWS) 
  17. void notOnWindows() { 
  18.     // ... 

2)不同的 Java 運行環(huán)境,可能也需要不同的測試用例。@EnabledOnJre 和 @EnabledForJreRange 注解就可以滿足這個需求。

 
 
 
 
  1. @Test 
  2. @EnabledOnJre(JAVA_8) 
  3. void onlyOnJava8() { 
  4.     // ... 
  5.  
  6. @Test 
  7. @EnabledOnJre({ JAVA_9, JAVA_10 }) 
  8. void onJava9Or10() { 
  9.     // ... 
  10.  
  11. @Test 
  12. @EnabledForJreRange(min = JAVA_9, max = JAVA_11) 
  13. void fromJava9to11() { 
  14.     // ... 

06、尾聲

最后,給你說三句心里話吧。在編寫單元測試的時候,你最好這樣做:

1)單元測試的代碼本身必須非常名單明了,能一下看明白,決不能再為測試代碼編寫測試代碼。

2)每個單元測試應(yīng)該互相獨立,不依賴運行時的順序。

3)測試時要特別注意邊界條件,比如說 0,null,空字符串"" 等情況。

希望我能盡早的替你發(fā)現(xiàn)代碼中的 bug,畢竟越早的發(fā)現(xiàn),造成的損失就會越小。see you!

 本文轉(zhuǎn)載自微信公眾號「沉默王二」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系沉默王二公眾號。


當前標題:JUnit:別再用 main 方法測試了,好嗎?
網(wǎng)頁地址:http://www.5511xx.com/article/cosidoh.html