編寫更好的Java單元測(cè)試的七個(gè)技巧_第1頁
編寫更好的Java單元測(cè)試的七個(gè)技巧_第2頁
編寫更好的Java單元測(cè)試的七個(gè)技巧_第3頁
編寫更好的Java單元測(cè)試的七個(gè)技巧_第4頁
編寫更好的Java單元測(cè)試的七個(gè)技巧_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、編寫更好的Java單元測(cè)試的七個(gè)技巧測(cè)試是開發(fā)的一個(gè)非常重要的方面,可以在很大程度上決定一個(gè)應(yīng)用程序的命運(yùn)。良好的測(cè)試可以在早期捕獲導(dǎo)致應(yīng)用程序崩潰的問題,但較差的測(cè)試往往總是導(dǎo)致故障和停機(jī)。作者:小峰來源:碼農(nóng)網(wǎng)|2016-12-13 10:06 收藏   分享   測(cè)試是開發(fā)的一個(gè)非常重要的方面,可以在很大程度上決定一個(gè)應(yīng)用程序的命運(yùn)。良好的測(cè)試可以在早期捕獲導(dǎo)致應(yīng)用程序崩潰的問題,但較差的測(cè)試往往總是導(dǎo)致故障和停機(jī)。雖然有三種主要類型的軟件測(cè)試:?jiǎn)卧獪y(cè)試,功能測(cè)試和集成測(cè)試,但是在這篇博文中,我們將討論開發(fā)人員級(jí)單元測(cè)試。在我深入講述具體

2、細(xì)節(jié)之前,讓我們先來回顧一下這三種測(cè)試的詳細(xì)內(nèi)容。軟件開發(fā)測(cè)試的類型單元測(cè)試用于測(cè)試各個(gè)代碼組件,并確保代碼按照預(yù)期的方式工作。單元測(cè)試由開發(fā)人員編寫和執(zhí)行。大多數(shù)情況下,使用JUnit或TestNG之類的測(cè)試框架。測(cè)試用例通常是在方法級(jí)別寫入并通過自動(dòng)化執(zhí)行。集成測(cè)試檢查系統(tǒng)是否作為一個(gè)整體而工作。集成測(cè)試也由開發(fā)人員完成,但不是測(cè)試單個(gè)組件,而是旨在跨組件測(cè)試。系統(tǒng)由許多單獨(dú)的組件組成,如代碼,數(shù)據(jù)庫,Web服務(wù)器等。集成測(cè)試能夠發(fā)現(xiàn)如組件布線,網(wǎng)絡(luò)訪問,數(shù)據(jù)庫問題等問題。功能測(cè)試通過將給定輸入的結(jié)果與規(guī)范進(jìn)行比較來檢查每個(gè)功能是否正確實(shí)現(xiàn)。通常,這不是在開發(fā)人員級(jí)別的。功能測(cè)試由單獨(dú)的測(cè)

3、試團(tuán)隊(duì)執(zhí)行。測(cè)試用例基于規(guī)范編寫,并且實(shí)際結(jié)果與預(yù)期結(jié)果進(jìn)行比較。有若干工具可用于自動(dòng)化的功能測(cè)試,如Selenium和QTP。如前所述,單元測(cè)試可幫助開發(fā)人員確定代碼是否正常工作。在這篇博文中,我將提供在Java中單元測(cè)試的有用提示。1.使用框架來用于單元測(cè)試Java提供了若干用于單元測(cè)試的框架。TestNG和JUnit是最流行的測(cè)試框架。JUnit和TestNG的一些重要功能:· 易于設(shè)置和運(yùn)行。· 支持注釋。· 允許忽略或分組并一起執(zhí)行某些測(cè)試。· 支持參數(shù)化測(cè)試,即通過在運(yùn)行時(shí)指定不同的值來運(yùn)行單元測(cè)試。· 通過與構(gòu)建工具,如Ant,M

4、aven和Gradle集成來支持自動(dòng)化的測(cè)試執(zhí)行。EasyMock是一個(gè)模擬框架,是單元測(cè)試框架,如JUnit和TestNG的補(bǔ)充。EasyMock本身不是一個(gè)完整的框架。它只是添加了創(chuàng)建模擬對(duì)象以便于測(cè)試的能力。例如,我們想要測(cè)試的一個(gè)方法可以調(diào)用從數(shù)據(jù)庫獲取數(shù)據(jù)的DAO類。在這種情況下,EasyMock可用于創(chuàng)建返回硬編碼數(shù)據(jù)的MockDAO。這使我們能夠輕松地測(cè)試我們意向的方法,而不必?fù)?dān)心數(shù)據(jù)庫訪問。2.謹(jǐn)慎使用測(cè)試驅(qū)動(dòng)開發(fā)!測(cè)試驅(qū)動(dòng)開發(fā)(TDD)是一個(gè)軟件開發(fā)過程,在這過程中,在開始任何編碼之前,我們基于需求來編寫測(cè)試。由于還沒有編碼,測(cè)試最初會(huì)失敗。然后寫入最小量的代碼以通過測(cè)試。然

5、后重構(gòu)代碼,直到被優(yōu)化。目標(biāo)是編寫覆蓋所有需求的測(cè)試,而不是一開始就寫代碼,卻可能甚至都不能滿足需求。TDD是偉大的,因?yàn)樗鼘?dǎo)致簡(jiǎn)單的模塊化代碼,且易于維護(hù)??傮w開發(fā)速度加快,容易發(fā)現(xiàn)缺陷。此外,單元測(cè)試被創(chuàng)建作為TDD方法的副產(chǎn)品。然而,TDD可能不適合所有的情況。在設(shè)計(jì)復(fù)雜的項(xiàng)目中,專注于最簡(jiǎn)單的設(shè)計(jì)以便于通過測(cè)試用例,而不提前思考可能會(huì)導(dǎo)致巨大的代碼更改。此外,TDD方法難以用于與遺留系統(tǒng),GUI應(yīng)用程序或與數(shù)據(jù)庫一起工作的應(yīng)用程序交互的系統(tǒng)。另外,測(cè)試需要隨著代碼的改變而更新。因此,在決定采用TDD方法之前,應(yīng)考慮上述因素,并應(yīng)根據(jù)項(xiàng)目的性質(zhì)采取措施。3.測(cè)量代碼覆蓋率代碼覆蓋率衡量(

6、以百分比表示)了在運(yùn)行單元測(cè)試時(shí)執(zhí)行的代碼量。通常,高覆蓋率的代碼包含未檢測(cè)到的錯(cuò)誤的幾率要低,因?yàn)槠涓嗟脑创a在測(cè)試過程中被執(zhí)行。測(cè)量代碼覆蓋率的一些最佳做法包括:· 使用代碼覆蓋工具,如Clover,Corbetura,JaCoCo或Sonar。使用工具可以提高測(cè)試質(zhì)量,因?yàn)檫@些工具可以指出未經(jīng)測(cè)試的代碼區(qū)域,讓你能夠開發(fā)開發(fā)額外的測(cè)試來覆蓋這些領(lǐng)域。· 每當(dāng)寫入新功能時(shí),立即寫新的測(cè)試覆蓋。· 確保有測(cè)試用例覆蓋代碼的所有分支,即if / else語句。高代碼覆蓋不能保證測(cè)試是完美的,所以要小心!下面的concat方法接受布爾值作為輸入,并且僅當(dāng)布爾值為t

7、rue時(shí)附加傳遞兩個(gè)字符串:1. public String concat(boolean append, String a,String b)  2.         String result = null; 3.         If (append)  4.   

8、;          result = a + b; 5.                              6.    

9、     return result.toLowerCase(); 7.  以下是上述方法的測(cè)試用例: 1. Test 2. public void testStringUtil()  3.      String result = stringUtil.concat(true, "Hello ", "World");

10、 System.out.println("Result is "+result); 4.  在這種情況下,執(zhí)行測(cè)試的值為true。當(dāng)測(cè)試執(zhí)行時(shí),它將通過。當(dāng)代碼覆蓋率工具運(yùn)行時(shí),它將顯示100%的代碼覆蓋率,因?yàn)閏oncat方法中的所有代碼都被執(zhí)行。但是,如果測(cè)試執(zhí)行的值為false,則將拋出NullPointerException。所以100%的代碼覆蓋率并不真正表明測(cè)試覆蓋了所有場(chǎng)景,也不能說明測(cè)試良好。4.盡可能將測(cè)試數(shù)據(jù)外部化在JUnit4之前,測(cè)試用例要運(yùn)行的數(shù)據(jù)必須硬編碼到測(cè)試用例中。這導(dǎo)致了限制,為了使用不同的

11、數(shù)據(jù)運(yùn)行測(cè)試,測(cè)試用例代碼必須修改。但是,JUnit4以及TestNG支持外部化測(cè)試數(shù)據(jù),以便可以針對(duì)不同的數(shù)據(jù)集運(yùn)行測(cè)試用例,而無需更改源代碼。下面的MathChecker類有方法可以檢查一個(gè)數(shù)字是否是奇數(shù): 1. public class MathChecker  2.         public Boolean isOdd(int n)  3.       &

12、#160;     if (n%2 != 0)  4.                 return true; 5.              else  6. 

13、60;               return false; 7.              8.          9.      以下是MathCheck

14、er類的TestNG測(cè)試用例: 1. public class MathCheckerTest  2.         private MathChecker checker; 3.         BeforeMethod 4.         public void

15、 beforeMethod()  5.           checker = new MathChecker(); 6.          7.         Test 8.       

16、;  Parameters("num") public void isOdd(int num)  System.out.println("Running test for "+num); Boolean result = checker.isOdd(num); Assert.assertEquals(result, new Boolean(true); 9. 

17、0;        10.      TestNG以下是testng.xml(用于TestNG的配置文件),它具有要為其執(zhí)行測(cè)試的數(shù)據(jù):1. <xml version="1.0" encoding="UTF-8"?> 2. <suite name="ParameterExampleSuite" parallel="false&qu

18、ot;> 3. <test name="MathCheckerTest"> 4. <classes> 5.   <parameter name="num" value="3"></parameter> 6.   <class name="com.stormpath.demo.MathCheckerTest"/> 7. &l

19、t;/classes> 8.  </test> 9.  <test name="MathCheckerTest1"> 10. <classes> 11.   <parameter name="num" value="7"></parameter> 12.   <class name="com.stormpa

20、th.demo.MathCheckerTest"/> 13. </classes> 14.  </test> 15. </suite> 可以看出,在這種情況下,測(cè)試將執(zhí)行兩次,值3和7各一次。除了通過XML配置文件指定測(cè)試數(shù)據(jù)之外,還可以通過DataProvider注釋在類中提供測(cè)試數(shù)據(jù)。JUnit與TestNG類似,測(cè)試數(shù)據(jù)也可以外部化用于JUnit。以下是與上述相同MathChecker類的JUnit測(cè)試用例:1. RunWith(Parameterized.class) 2.

21、public class MathCheckerTest  3.  private int inputNumber; 4.  private Boolean expected; 5.  private MathChecker mathChecker; 6.  Before 7.  public void setup() 8.     &#

22、160;mathChecker = new MathChecker(); 9.   10.     / Inject via constructor 11.     public MathCheckerTest(int inputNumber, Boolean expected)  12.      

23、0;  this.inputNumber = inputNumber; 13.         this.expected = expected; 14.      15.     Parameterized.Parameters 16.     public static Co

24、llection<Object> getTestData()  17.         return Arrays.asList(new Object 18.                 1, true, 19.     &

25、#160;           2, false, 20.                 3, true, 21.               &#

26、160; 4, false, 22.                 5, true 23.         ); 24.      25.     Test 26.   

27、0; public void testisOdd()  27.         System.out.println("Running test for:"+inputNumber); 28.         assertEquals(mathChecker.isOdd(inputNumber), expected); 

28、;29.      30.  可以看出,要對(duì)其執(zhí)行測(cè)試的測(cè)試數(shù)據(jù)由getTestData()方法指定。此方法可以輕松地修改為從外部文件讀取數(shù)據(jù),而不是硬編碼數(shù)據(jù)。5.使用斷言而不是Print語句許多新手開發(fā)人員習(xí)慣于在每行代碼之后編寫System.out.println語句來驗(yàn)證代碼是否正確執(zhí)行。這種做法常常擴(kuò)展到單元測(cè)試,從而導(dǎo)致測(cè)試代碼變得雜亂。除了混亂,這需要開發(fā)人員手動(dòng)干預(yù)去驗(yàn)證控制臺(tái)上打印的輸出,以檢查測(cè)試是否成功運(yùn)行。更好的方法是使用自動(dòng)指示測(cè)試結(jié)果的斷言。下面的StringUti類是一個(gè)簡(jiǎn)單類,有一個(gè)連接兩個(gè)輸入字符串并

29、返回結(jié)果的方法:1. public class StringUtil  2.         public String concat(String a,String b)  3.             return a + b; 4.  

30、0;       5.      以下是上述方法的兩個(gè)單元測(cè)試:1. Test 2.     public void testStringUtil_Bad()  3.          String result = stringUtil.concat("He

31、llo ", "World"); 4.          System.out.println("Result is "+result); 5.      6.     Test 7.     public void testStringU

32、til_Good()  8.          String result = stringUtil.concat("Hello ", "World"); 9.          assertEquals("Hello World", result);

33、0;10.      testStringUtil_Bad將始終傳遞,因?yàn)樗鼪]有斷言。開發(fā)人員需要手動(dòng)地在控制臺(tái)驗(yàn)證測(cè)試的輸出。如果方法返回錯(cuò)誤的結(jié)果并且不需要開發(fā)人員干預(yù),則testStringUtil_Good將失敗。6.構(gòu)建具有確定性結(jié)果的測(cè)試一些方法不具有確定性結(jié)果,即該方法的輸出不是預(yù)先知道的,并且每一次都可以改變。例如,考慮以下代碼,它有一個(gè)復(fù)雜的函數(shù)和一個(gè)計(jì)算執(zhí)行復(fù)雜函數(shù)所需時(shí)間(以毫秒為單位)的方法:1. public class DemoLogic  2.  private&#

34、160;void veryComplexFunction() 3.      /This is a complex function that has a lot of database access and is time consuming 4.      /To demo this 

35、method, I am going to add a Thread.sleep for a random number of milliseconds 5.      try  6.          int time = (int) (Math.rando

36、m()*100); 7.          Thread.sleep(time); 8.       catch (InterruptedException e)  9.          / TODO Auto-generated catch block 10.          e.pr

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論