在像 Eclipse 那樣的 IDE 中或者比如在 Ant 構建腳本中運行單元測試是確保應用程序質量的一個很好的開始;然而,版本控制庫(如 Subversion)中的源代碼一改變,在單獨無變動的構建機上運行單元測試就有助于檢驗開發生命周期中的問題。而且,運行各種類型的開發人員測試,如組件測試、功能測試和性能測試,能夠在開發生命周期中更早地 將問題顯示出來。
關于本系列
作為開發人員,我們的工作就是為終端用戶實現過程自動化;然而,很多開發人員卻忽略了將自己的開發過程自動化的機會。為此,我編寫了 讓開發自動化 這個系列的文章,專門探討軟件開發過程自動化的實際應用,并教您何時 以及如何 成功地應用自動化。
通常在持續集成(CI)環境中運行的開發人員測試有效地扮演著代碼質量聚光燈的角色。這是因為如果能有效地編寫這些測試,則幾乎能夠在問題(如缺陷)產生之時就將其發現。不經常運行測試通常就不怎么有效,因為從產生缺陷到發現該缺陷的時間相隔很長,但持續地(即,每一次代碼改變時)運行測試能確??焖侔l現無意識的行為。
本文涵蓋下列內容:
通過 Ant 運行 JUnit 測試
使用 JUnit 和 DbUnit 執行更長時間的運行組件測試
使用 JUnitPerf 確定哪些方法花費時間過久而執行失敗
用 Cobertura 訪問代碼覆蓋率
用 CruiseControl 進行持續測試
我提供一個關于不同類型開發人員測試的概覽,和一些可以添加到構建過程并使用 Continuous Integration 系統持續運行的例子。
按 JUnit 進行單元測試
有人稱之為單元測試,有人稱之為組件測試
經常提到的單元測試其實更像是一個組件級別的測試。組件測試通常驗證不止一個類,并且依賴于一些東西,如數據庫或其他重量級系統,如文件系統。但是更重要的是,在測試的基礎上進行測試,組件測試比單元測試運行時間更長。
有時,我聽到開發人員將開發人員測試這一術語與簡單的單元測試相混淆;然而,我發現將單元測試這一術語提練得更加明確很有幫助。對我來說,單元測試是快速運行的 測試,通常測試沒有大的外部依賴項(如數據庫)的單獨的類。例如,清單 1 定義了一個單元測試,該測試使用 JUnit 來驗證一個叫做 BeerDaoStub 的存根數據類。針對并未真正連接到數據庫的接口的測試技術是一種驗證業務功能的方法,使用該方法不會導致花費昂貴的設置成本。另外,這樣做可使測試保持為一個真正的單元測試。
清單 1. 一個簡單的單元測試
public void setUp() { beerService = new BeerDaoStub(); } public void testUnitGetBeer() { Collection beers = beerService.findAll(); assertTrue(beers != null && beers.size() > 0); } |
一旦編寫了一些單元測試,就可以一直通過 IDE 運行這些測試,但您也想要將這些測試作為構建過程的一部分來運行。確保該測試通過構建過程成功運行意味著也能從 CI 構建的上下文中啟動這些相同的測試。
清單 2 是一個 Ant 腳本片段,介紹了執行一批單元測試的 junit 任務。這項任務與 JUnit 一起運作,其妙處在于:定義過的所有測試現在都能自動運行并且如果其中任何一個測試失敗,則構建也將失敗 —— 通過使用 haltonfailure 屬性實現。
清單 2. 在 Ant 中運行單元測試
<junit fork="yes" haltonfailure="true" dir="${basedir}" printsummary="yes"> <classpath refid="test.class.path" /> <classpath refid="project.class.path"/> <formatter type="plain" usefile="true" /> <formatter type="xml" usefile="true" /> <batchtest fork="yes" todir="${logs.junit.dir}"> <fileset dir="${test.unit.dir}"> <patternset refid="test.sources.pattern"/> </fileset> </batchtest> </junit> |
注意:test.unit.dir 指定測試的位置。這是將這些測試(在本例中為單元測試)和其他測試隔離起來的有效方法。通過利用這項技術,可以通過定義另外的 Ant 目標來先運行較快的測試,接著運行較慢的測試(如組件測試、功能測試和系統測試)。
回頁首
集合組件測試
由于單元測試執行得相當快,很容易將它們作為構建的一部分經常運行。但這些測試并未達到一個高的代碼覆蓋率 —— 其隔離的本質決定了它們只測試一部分功能。編寫具有更多代碼(從而可實現更多功能)的測試通常要以附屬框架的形式執行更多的調查工作。一旦開始使用這些幫助框架來編寫測試,這些測試就開始成為更高級別的測試,我把它們歸類為組件測試。
組件測試是基本的測試,這些測試將驗證不止一個類,且通常依賴于外部依賴項,如數據庫。組件測試的編寫方式和單元測試大體一致,只是前者并非通過模擬或存根類來強制隔離,實現這些測試可謂勉為其難,但可以利用框架來便利對外部依賴項的使用。例如,我通常使用 DbUnit 框架來幫助管理數據庫,以便組件測試可驗證依賴數據庫數據的代碼功能。
用 DbUnit 控制數據庫狀態
DbUnit 是一個框架,它使針對數據庫的測試過程變得更加簡單。它提供了一個標準 XML 格式,用于定義一些測試數據,以便從數據庫中選擇、更新、插入和刪除數據。請牢記,DbUnit 并沒有替換數據庫;它只是提供了一種更加有效的機制來處理測試數據。您可以用 DbUnit 來編寫依賴于特定數據的測試,DbUnit 保證該數據位于底層的數據庫中。
原文轉自:http://www.ibm.com/developerworks/cn/java/j-ap03137/index.html