JUNIT
基本簡介
JUnit是一個開發原始碼的Java測試框架,用於編寫和運行可重複的測試。他是用於單元測試框架體系xUnit的一個實例(用於java語言)。它包括以下特性:
1、用於測試期望結果的斷言(Assertion);2、用於共享共同測試數據的測試工具;3、用於方便的組織和運行測試的測試套件;4、圖形和文本的測試運行器。
測試流程:1、擴展TestCase類;2、覆蓋runTest()方法(可選);3、對應測試目標類書寫testXXXXX()方法;4、擴展TestSuite類,重載suite()方法,實現自定義的測試過程;5、運行TestRunner進行測試;
功能作用
junit是在xp編程和重構(refactor)中被極力推薦使用的工具,因為在實現自動單元測試的情況下可以大大的提高開發的效率,但是實際上編寫測試代碼也是需要耗費很多的時間和精力的:
1、對於xp編程而言,要求在編寫代碼之前先寫測試,這樣可以強制你在寫代碼之前好好的思考代碼(方法)的功能和邏輯,否則編寫的代碼很不穩定,那麼你需要同時維護測試代碼和實際代碼,這個工作量就會大大增加。因此在xp編程中,基本過程是這樣的:構思-》編寫測試代碼-》編寫代碼-》測試,而且編寫測試和編寫代碼都是增量式的,寫一點測一點,在編寫以後的代碼中如果發現問題可以較塊的追蹤到問題的原因,減小回歸錯誤的糾錯難度。
2、對於重構而言,其好處和xp編程中是類似的,因為重構也是要求改一點測一點,減少回歸錯誤造成的時間消耗。
3、對於非以上兩種情況,在開發的時候使用junit寫一些適當的測試也是有必要的,因為一般也是需要編寫測試的代碼的,可能原來不是使用的junit,如果使用junit,而且針對接口(方法)編寫測試代碼會減少以後的維護工作,例如以後對方法內部的修改(這個就是相當於重構的工作了)。另外就是因為junit有斷言功能,如果測試結果不通過會那個測試不通過,為什麼,而如果是想以前的一般做法是寫一些測試代碼看其輸出結果,然後再由自己來判斷結果使用正確,使用junit的好處就是這個結果是否正確的判斷是它來完成的,只需要看看它告訴結果是否正確就可以了,在一般情況下會大大提高效率。
框架介紹
一、TestCase
測試用例,對每個測試類,都要定義一個測試用例。JUnit支持兩種運行單個測試的方法:靜態的和動態的方法。
1、靜態的方法就是覆蓋TestCase類的runTest()方法,一般是採用內部類的方式
創建一個測試實例: TestCase test01 = new testCar("test getWheels") { public void runTest() { testGetWheels();} }
採用靜態的方法要注意要給每個測試一個名字,這樣你就可以區分哪個測試失敗了。
2、動態的方法是用內省來實現runTest()以創建一個測試實例。這要求測試的名字就是需要調用的測試方法的名字: TestCase test01 = new testCar("testGetWheels");
JUnit會動態查找並調用指定的測試方法。動態的方法很簡潔,但如果你鍵入了錯誤的名字就會得到一個令人奇怪的NoSuchMethodException異常。動態的方法和靜態的方法都很好,你可以按照自己的喜好來選擇。
二、TestSuite
一旦你創建了一些測試實例,下一步就是要讓他們能一起運行。必須定義一個TestSuite。在JUnit中,這就要求你在TestCase類中定義一個靜態的suite()方法。suite()方法就像main()方法一樣,JUnit用它來執行測試。在suite()方法中,你將測試實例加到一個TestSuite對象中,並返回這個TestSuite對象。一個TestSuite對象可以運行一組測試。TestSuite和TestCase都實現了Test接口,而Test接口定義了運行測試所需的方法。這就允許你用TestCase和TestSuite的組合創建一個TestSuite。public static Test suite() { TestSuite suite= new TestSuite(); suite.addTest(new testCar("testGetWheels")); suite.addTest(new testCar("testGetSeats")); return suite; }public static Test suite() { return new TestSuite(testCar.class); }
三、TestRunner
有了TestSuite就可以運行這些測試了,JUnit提供了三種界面來運行測試 [Text UI] junit.textui.TestRunner [AWT UI] junit.awtui.TestRunner [Swing UI] junit.swingui.TestRunner java junit.textui.TestRunner yourTestclass
Fixture
如果需要在一個或若干個的類執行多個測試,這些類就成為了測試的context。在JUnit中被稱為Fixture。當你編寫測試代碼時,你會發現你花費了很多時間配置/初始化相關測試的Fixture。將配置Fixture的代碼放入測試類的構造方法中並不可取,因為要求執行多個測試,我並不希望某個測試的結果意外地影響其他測試的結果。通常若干個測試會使用相同的Fixture,而每個測試又各有自己需要改變的地方。 為此,JUnit提供了兩個方法,定義在Test Case類中。
protected void setUp() throws java.lang.Exception protected void tearDown() throws java.lang.Exception 覆蓋setUp()方法,初始化所有測試的Fixture,如建立資料庫連接,將每個測試略有不同的地方在testXXX()方法中進行配置。覆蓋tearDown(),釋放你在setUp()中分配的永久性資源,如資料庫連接。 當JUnit執行測試時,它在執行每個testXXXXX()方法前都調用setUp(),而在執行每個testXXXXX()方法後都調用tearDown()方法,由此保證了測試不會相互影響。
四、Assert
Assert類中定義了相當多的assert方法,主要有assert(),assertEquals(), assertNull(), assertSame(), assertTrue(), fail()等方法。Faile失敗是一個期望的被assert方法檢查到的結果。Error錯誤則是意外的問題引起的,如ArrayIndexOutOfBoundsException。
實踐方法
1、不要用TestCase的構造函數初始化Fixture,而要用setUp()和tearDown()方法。2、不要依賴或假定測試運行的順序,因為JUnit利用Vector保存測試方法。所以不同的平台會按不同的順序從Vector中取出測試方法。3、避免編寫有副作用的Test Case。例如:如果隨後的測試依賴於某些特定的交易數據,就不要提交交易數據。簡單的會滾就可以了。4、當繼承一個測試類時,記得調用父類的setUp()和tearDown()方法。5、將測試代碼和工作代碼放在一起,一邊同步編譯和更新。(使用Ant中有支持junit的task.)6、測試類和測試方法應該有一致的命名方案。如在工作類名前加上test從而形成測試類名。7、確保測試與時間無關,不要依賴使用過期的數據進行測試。導致在隨後的維護過程中很難重現測試。8、如果你編寫的軟體面向國際市場,編寫測試時要考慮國際化的因素。不要僅用母語的Locale進行測試。9、儘可能地利用JUnit提供地assert/fail方法以及異常處理的方法,可以使代碼更為簡潔。10、測試要儘可能地小,執行速度快。
和ant結合
ant提供了兩個target:junit和junitreport運行所有測試用例,並生成html格式的報表。具體操作如下:
1、將junit.jar放在ANT_HOMElib目錄下2、修改build.xml,加入如下內容:--------------One or more tests failed,check the report for detail---------------
運行這個target,ant會運行每個TestCase,在report目錄下就有了很多TEST*.xml和一些網頁打開report目錄下的index.html就可以看到很直觀的測試運行報告,一目了然。在Eclipse中開發、運行JUnit測試相當簡單。因為Eclipse本身集成了JUnit相關組件,並對JUnit的運行提成了無縫的支持。