国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

JUnit:別再用 main 方法測試了,好嗎?

開發(fā) 后端
在了解我之前,先來了解一下什么是單元測試。單元測試,就是針對最小的功能單元編寫測試代碼。在 Java 中,最小的功能單元就是方法,因此,對 Java 程序員進(jìn)行單元測試實際上就是對 Java 方法的測試。

[[361023]]

01、前世今生

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

為什么要進(jìn)行單元測試呢?因為單元測試可以確保你編寫的代碼是符合軟件需求和遵循開發(fā)規(guī)范的。單元測試是所有測試中最底層的一類測試,是第一個環(huán)節(jié),也是最重要的一個環(huán)節(jié),是唯一一次能夠達(dá)到代碼覆蓋率 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 的話,就不會再有這種困擾了。我可以非常簡單地組織測試代碼,并隨時運行它們,還能給出準(zhǔn)確的測試報告,讓你在最短的時間內(nèi)發(fā)現(xiàn)自己編寫的代碼到底哪里出了問題。

02、上手指南

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

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

 

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

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

 

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

 

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

  1. <dependency> 
  2.     <groupId>org.junit.jupiter</groupId> 
  3.     <artifactId>junit-jupiter</artifactId> 
  4.     <version>RELEASE</version> 
  5.     <scope>compile</scope> 
  6. </dependency> 

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

  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() 對期望的值和實際的值進(jìn)行比對。

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

 

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

 

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

03、瞻前顧后

在一個測試用例中,可能要對多個方法進(jìn)行測試。在測試之前呢,需要準(zhǔn)備一些條件,比如說創(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 程序來說,異常處理也非常的重要。對于可能拋出的異常進(jìn)行測試,本身也是測試的一個重要環(huán)節(jié)。

還拿之前的 Factorial 類來進(jìn)行說明。在 fact() 方法的一開始,對參數(shù) n 進(jì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 表達(dá)式。

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

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)系沉默王二公眾號。

 

責(zé)任編輯:武曉燕 來源: 沉默王二
相關(guān)推薦

2025-08-13 03:00:00

2025-05-19 04:00:00

2017-11-22 15:13:20

集成測試自動化測試契約測試

2025-11-03 04:00:00

2023-09-14 12:03:30

空指針判空

2021-06-09 06:41:11

OFFSETLIMIT分頁

2021-05-25 09:30:44

kill -9Linux kill -9 pid

2023-10-26 16:33:59

float 布局前段CSS

2020-12-04 10:05:00

Pythonprint代碼

2020-12-15 08:06:45

waitnotifyCondition

2021-01-29 11:05:50

PrintPython代碼

2020-12-02 11:18:50

print調(diào)試代碼Python

2020-12-03 09:05:38

SQL代碼方案

2024-12-26 07:47:20

2020-07-17 07:15:38

數(shù)據(jù)庫ID代碼

2022-01-27 07:48:37

虛擬項目Django

2012-03-13 16:14:09

JavaJUnit

2025-05-15 03:00:00

2022-03-10 10:12:04

自動化腳本Bash

2025-08-06 09:31:12

點贊
收藏

51CTO技術(shù)棧公眾號

男人的天堂成人| 国产精品视频分类| 亚洲小说春色综合另类电影| 欧美日韩视频在线第一区 | 自拍偷拍亚洲激情| 日韩精品综合在线| 麻豆视频观看网址久久| 久久久久久九九| 影音先锋成人在线电影| 国产精品久久久久久久久久久久久久| 国产精品毛片aⅴ一区二区三区| 亚洲精品久久久久中文字幕欢迎你| 免费在线观看av| 欧美三级日韩在线| 国产大学生校花援交在线播放| 一本久久a久久精品亚洲| 免费三级欧美电影| 一区二区三区在线不卡| 色综合天天色综合| 中文字幕一区在线| 国产经典视频一区| 亚洲一区二区三区四区的| 国产二区三区四区| 曰韩精品一区二区| 香蕉av一区| 欧美色网站导航| 色网在线观看| 亚洲天堂第一页| 激情五月综合婷婷| 欧美亚洲一级片| 99精品视频精品精品视频| 91在线精品观看| 99pao成人国产永久免费视频| 欧美一区二区三区精美影视| 久久99精品一区二区三区| 亚洲国产精品无码av| 91视视频在线观看入口直接观看www| 日韩avxxx| 一区二区视频在线| 黄色大片在线看| 欧美成人一级视频| 国产精品.xx视频.xxtv| 欧美激情综合色| 国产剧情一区| 久久久一本精品99久久精品66 | 在线观看免费视频你懂的| 亚洲第一网中文字幕| 亚洲高清黄色| 久久精品人人爽| 精品一区欧美| 久久青青草原| av在线不卡网| 国产特级嫩嫩嫩bbb| 在线观看视频一区二区| а√天堂资源官网在线资源 | 日韩成人免费av| 日韩av免费在线播放| 亚洲视频福利| 成人在线观看毛片| 国产精品理伦片| 日本高清中文字幕在线| 一区二区三区亚洲| 视频国产一区| 日韩在线电影一区| 91麻豆视频网站| 亚洲女人天堂| 亚洲欧美色图片| 精品一区二区三区在线| 台湾成人av| 亚洲免费观看高清完整版在线| 超碰在线观看免费版| 九九九久久久久久| 一区二区日韩免费看| 欧美成人免费高清视频| 欧美群妇大交群中文字幕| 国产高清亚洲| av色综合网| 久久久久久免费网| 日本www在线| 国自在线精品视频| 奇米777欧美一区二区| 免费观看的av网站| 亚洲精品91美女久久久久久久| 欧美人妖在线| 久久久久久久久久久久久国产| 亚洲成年人影院| 欧美不卡高清一区二区三区| 99c视频在线| 国产欧美一区二区精品秋霞影院| www视频在线免费观看| 国产成人综合av| www.激情成人| 第一av在线| 国产在线观看一区二区三区| 久久综合九色综合久久久精品综合| 成人短视频在线观看| 国产精品日韩欧美综合| 久久午夜老司机| 免费高潮视频95在线观看网站| 7777精品久久久大香线蕉小说| 日本一区二区免费在线观看视频| 国产91综合一区在线观看| 猫咪av永久| 日韩成人av一区| 日本一区二区在线看| 91午夜在线观看| 制服丝袜中文字幕亚洲| 欧美**字幕| 草草视频在线免费观看| 色猫猫国产区一区二在线视频| 日韩精品一级| 欧美 另类 交| 在线看不卡av| 深爱激情久久| 美脚丝袜脚交一区二区| 日韩欧美一区二区免费| 色88久久久久高潮综合影院| www国产精品内射老熟女| 精品捆绑美女sm三区| 日韩欧美视频专区| 波多野结衣天堂| 日韩极品精品视频免费观看| 亚洲国产精品第一区二区三区| 91天堂在线| 91超碰caoporn97人人| av一区二区三区黑人| 欧美电影网站| 欧洲av一区| 欧美视频你懂的| 国产精品99久久久久久动医院| 美女av在线免费观看| 欧美激情视频在线免费观看 欧美视频免费一| 国产精品自拍毛片| 超碰中文在线| 色一情一乱一伦一区二区三区| 欧美日韩国产天堂| 一区二区亚洲| yw视频在线观看| 成人久久一区二区三区| 亚洲午夜精品久久久久久久久| 精品国产欧美日韩| 免费国产视频| 国产精品一区二区三区毛片淫片| 亚洲综合一二区| 日韩精品免费一区二区三区| 在线播放网站| 91成人免费看| 欧美狂野另类xxxxoooo| 可以看av的网站久久看| sqte在线播放| 97在线免费视频观看| 中文字幕日韩av电影| 91欧美激情一区二区三区成人| 日韩精品视频一区二区三区| 五月婷婷之综合激情| 国产成一区二区| 欧美日韩亚洲视频| 中文高清一区| 2022成人影院| 999精品网站| 欧美在线视频网站| 天堂网av成人| 色婷婷久久久综合中文字幕 | 日韩中文理论片| 成人av片在线观看| 国产va免费精品观看精品| 欧美成人黑人猛交| 国产精品久久久久久久久久新婚| 午夜不卡av在线| 亚洲精品影院在线观看| 亚洲校园激情春色| 激情五月色综合亚洲小说| 亚洲最大福利网站| 亚洲精品国产欧美| 中国av一区二区三区| 亚洲精品在线观看91| 亚洲区欧洲区| 成人中文字幕av| 成人有码在线视频| 亚洲激情自拍图| 国产精品理论片在线观看| 日本欧美国产| free性欧美| 免费成人黄色网址| 狠狠色综合网站久久久久久久| 国产亚洲美女精品久久久| 亚洲另类色综合网站| 麻豆九一精品爱看视频在线观看免费| ww久久综合久中文字幕| 在线视频您懂的| 999精品网站| 国产精品一区二区久久精品爱涩| 加勒比av一区二区| 欧美性少妇18aaaa视频| 日韩在线欧美在线| 日韩精品久久一区二区| 亚洲性色av| 中文字幕区一区二区三| 日韩理论片一区二区| 日韩一区视频在线|