JUnit最佳實現

magus_yang發表於2004-09-01

轉載自:http://www.sawin.com.cn/doc/SA/NewTech/junit1.htm


JUnit是什麼? 

cherami


JUnit是一個開發原始碼的Java測試框架,用於編寫和執行可重複的測試。他是用於單元測試框架體系xUnit的一個例項(用於java語言)。它包括以下特性:
1、用於測試期望結果的斷言(Assertion)
2、用於共享共同測試資料的測試工具
3、用於方便的組織和執行測試的測試套件
4、圖形和文字的測試執行器

JUnit最初是由Erich Gamma(GoF之一)和Kent Beck(xp和refactor的先驅之一)編寫的. 

需要說明的是junit一般是用來進行單元測試的,因此需要了解被測試程式碼的內部結構(即所謂的白盒測試),另外junit是在xp程式設計和重構(refactor)中被極力推薦使用的工具,因為在實現自動單元測試的情況下可以大大的提高開發的效率,但是實際上編寫測試程式碼也是需要耗費很多的時間和精力的,那麼使用這個東東好處到底在哪裡呢?筆者認為是這樣的:
1、對於xp程式設計而言,要求在編寫程式碼之前先寫測試,這樣可以強制你在寫程式碼之前好好的思考程式碼(方法)的功能和邏輯,否則編寫的程式碼很不穩定,那麼你需要同時維護測試程式碼和實際程式碼,這個工作量就會大大增加。因此在xp程式設計中,基本過程是這樣的:構思-》編寫測試程式碼-》編寫程式碼-》測試,而且編寫測試和編寫程式碼都是增量式的,寫一點測一點,在編寫以後的程式碼中如果發現問題可以較塊的追蹤到問題的原因,減小回歸錯誤的糾錯難度
2、對於重構而言,其好處和xp程式設計中是類似的,因為重構也是要求改一點測一點,減少迴歸錯誤造成的時間消耗。
3、對於非以上兩種情況,我們在開發的時候使用junit寫一些適當的測試也是有必要的,因為一般我們也是需要編寫測試的程式碼的,可能原來不是使用的junit,如果使用junit,而且針對介面(方法)編寫測試程式碼會減少以後的維護工作,例如以後對方法內部的修改(這個就是相當於重構的工作了)。另外就是因為junit有斷言功能,如果測試結果不通過會告訴我們那個測試不通過,為什麼,而如果是想以前的一般做法是寫一些測試程式碼看其輸出結果,然後再由自己來判斷結果使用正確,使用junit的好處就是這個結果是否正確的判斷是它來完成的,我們只需要看看它告訴我們結果是否正確就可以了,在一般情況下會大大提高效率。

JUnit入門 

cherami 整理 


安裝JUnit

安裝很簡單,先到以下地址下載一個最新的zip包:
http://download.sourceforge.net/junit/
下載完以後解壓縮到你喜歡的目錄下,假設是JUNIT_HOME,然後將JUNIT_HOME下的junit.jar包加到你的系統的CLASSPATH環境變數中,對於IDE環境,對於需要用到的junit的專案增加到lib中,其設定不同的IDE有不同的設定,這裡不多講。


如何使用JUnit寫測試?

最簡單的範例如下:
1、建立一個TestCase的子類: 
package junitfaq;

import java.util.*;
import junit.framework.*;

public class SimpleTest extends TestCase {

public SimpleTest(String name) {
super(name);
}


2、寫一個測試方法斷言期望的結果:
public void testEmptyCollection() {
Collection collection = new ArrayList();
assertTrue(collection.isEmpty());
}
注意:JUnit推薦的做法是以test作為待測試的方法的開頭,這樣這些方法可以被自動找到並被測試。

3、寫一個suite()方法,它會使用反射動態的建立一個包含所有的testXxxx方法的測試套件:
public static Test suite() {
return new TestSuite(SimpleTest.class);
}

4、寫一個main()方法以文字執行器的方式方便的執行測試:
public static void main(String args[]) {
junit.textui.TestRunner.run(suite());
}
}

5、執行測試:
以文字方式執行:
java junitfaq.SimpleTest 

通過的測試結果是:

.
Time: 0

OK (1 tests)

Time上的小點表示測試個數,如果測試通過則顯示OK。否則在小點的後邊標上F,表示該測試失敗。
每次的測試結果都應該是OK的,這樣才能說明測試是成功的,如果不成功就要馬上根據提示資訊進行修正了。
如果JUnit報告了測試沒有成功,它會區分失敗(failures)和錯誤(errors)。失敗是你的程式碼中的assert方法失敗引起的;而錯誤則是程式碼異常引起的,例如ArrayIndexOutOfBoundsException。 


以圖形方式執行:

java junit.swingui.TestRunner junitfaq.SimpleTest 

通過的測試結果在圖形介面的綠色條部分。



以上是最簡單的測試樣例,在實際的測試中我們測試某個類的功能是常常需要執行一些共同的操作,完成以後需要銷燬所佔用的資源(例如網路連線、資料庫連線,關閉開啟的檔案等),TestCase類給我們提供了setUp方法和tearDown方法,setUp方法的內容在測試你編寫的TestCase子類的每個testXxxx方法之前都會執行,而tearDown方法的內容在每個testXxxx方法結束以後都會執行。這個既共享了初始化程式碼,又消除了各個測試程式碼之間可能產生的相互影響。 

JUnit最佳實踐 



Martin Fowler說過:“當你試圖列印輸出一些資訊或除錯一個表示式時,寫一些測試程式碼來替代那些傳統的方法。”一開始,你會發現你總是要建立一些新的Fixture,而且測試似乎使你的程式設計速度慢了下來。然而不久之後,你會發現你重複使用相同的Fixture,而且新的測試通常只涉及新增一個新的測試方法。 

你可能會寫許多測試程式碼,但你很快就會發現你設想出的測試只有一小部分是真正有用的。你所需要的測試是那些會失敗的測試,即那些你認為不會失敗的測試,或你認為應該失敗卻成功的測試。 

我們前面提到過測試是一個不會中斷的過程。一旦你有了一個測試,你就要一直確保其正常工作,以檢驗你所加入的新的工作程式碼。不要每隔幾天或最後才執行測試,每天你都應該執行一下測試程式碼。這種投資很小,但可以確保你得到可以信賴的工作程式碼。你的返工率降低了,你會有更多的時間編寫工作程式碼。 

不要認為壓力大,就不寫測試程式碼。相反編寫測試程式碼會使你的壓力逐漸減輕,應為通過編寫測試程式碼,你對類的行為有了確切的認識。你會更快地編寫出有效率地工作程式碼。

下面是一些具體的編寫測試程式碼的技巧或較好的實踐方法: 

1. 不要用TestCase的建構函式初始化Fixture,而要用setUp()和tearDown()方法。 

2. 不要依賴或假定測試執行的順序,因為JUnit利用Vector儲存測試方法。所以不同的平臺會按不同的順序從Vector中取出測試方法。 

3. 避免編寫有副作用的TestCase。例如:如果隨後的測試依賴於某些特定的交易資料,就不要提交交易資料。簡單的會滾就可以了。 

4. 當繼承一個測試類時,記得呼叫父類的setUp()和tearDown()方法。 

5. 將測試程式碼和工作程式碼放在一起,一邊同步編譯和更新。(使用Ant中有支援junit的task.) 

6. 測試類和測試方法應該有一致的命名方案。如在工作類名前加上test從而形成測試類名。 

7. 確保測試與時間無關,不要依賴使用過期的資料進行測試。導致在隨後的維護過程中很難重現測試。 

8. 如果你編寫的軟體面向國際市場,編寫測試時要考慮國際化的因素。不要僅用母語的Locale進行測試。 

9. 儘可能地利用JUnit提供地assert/fail方法以及異常處理的方法,可以使程式碼更為簡潔。
 
10.測試要儘可能地小,執行速度快。

JUnit和ant結合 

cherami 轉貼


ant 提供了兩個 target : junit 和 junitreport 
執行所有 測試用例 ,並生成 html 格式的報表 
具體操作如下: 

1.將 junit.jar 放在 ANT_HOME/lib 目錄下 
2.修改 build.xml ,加入如下 內容: 


<property name="report" value="report" /> <target name="junitreport" depends="clean, compile"> <junit printsummary="on" fork="true" haltonfailure="false" failureproperty="tests.failed" showoutput="true"> <classpath refid="myclasspath"/> <formatter type="xml"/> <batchtest todir="${report}"> <fileset dir="${build}"> <include name="**/*Test.*"/> </fileset> </batchtest> </junit> <junitreport todir="${report}"> <fileset dir="${report}"> <include name="TEST-*.xml"/> </fileset> <report format="frames" todir="${report}"/> </junitreport> <fail if="tests.failed"> --------------------------------------------------------- One or more tests failed, check the report for detail... --------------------------------------------------------- </fail> </target> 

執行 這個 target ,ant 會執行每個 TestCase 
在 report 目錄下就有了 很多 TEST*.xml 和 一些網頁 
開啟 report 目錄下的 index.html 就可以看到很直觀的測試執行報告,一目瞭然。

相關文章