用 Cobertura 測量測試覆蓋率
http://www-128.ibm.com/developerworks/cn/java/j-cobertura/用 Cobertura 測量測試覆蓋率找出隱藏 bug 的未測試到的代碼 ![]() |
![]() |
![]() |
級別: 初級 Elliotte Rusty Harold, 副教授, Polytechnic University 2005 年 5 月 26 日 Cobertura 是一種開源工具,它通過檢測基本的代碼,并觀察在測試包運行時執行了哪些代碼和沒有執行哪些代碼,來測量測試覆蓋率。除了找出未測試到的代碼并發現 bug 外,Cobertura 還可以通過標記無用的、執行不到的代碼來優化代碼,還可以提供 API 實際操作的內部信息。Elliotte Rusty Harold 將與您分享如何利用代碼覆蓋率的最佳實踐來使用 Cobertura。 盡管測試先行編程(test-first programming)和單元測試已不能算是新概念,但測試驅動的開發仍然是過去 10 年中最重要的編程創新。最好的一些編程人員在過去半個世紀中一直在使用這些技術,不過,只是在最近幾年,這些技術才被廣泛地視為在時間及成本預算內開發健壯的無缺陷軟件的關鍵所在。但是,測試驅動的開發不能超過測試所能達到的程度。測試改進了代碼質量,但這也只是針對實際測試到的那部分代碼而言的。您需要有一個工具告訴您程序的哪些部分沒有測試到,這樣就可以針對這些部分編寫測試代碼并找出更多 bug。 Mark Doliner 的 Cobertura (cobertura 在西班牙語是覆蓋的意思)是完成這項任務的一個免費 GPL 工具。Cobertura 通過用額外的語句記錄在執行測試包時,哪些行被測試到、哪些行沒有被測試到,通過這種方式來度量字節碼,以便對測試進行監視。然后它生成一個 HTML 或者 XML 格式的報告,指出代碼中的哪些包、哪些類、哪些方法和哪些行沒有測試到。可以針對這些特定的區域編寫更多的測試代碼,以發現所有隱藏的 bug。 我們首先查看生成的 Cobertura 輸出。圖 1 顯示了對 Jaxen 測試包運行 Cobertura 生成的報告(請參閱 參考資料)。從該報告中,可以看到從很好(在 圖 1. Jaxen 的包級別覆蓋率統計數據 ![]() Cobertura 通過被測試的行數和被測試的分支數來計算覆蓋率。第一次測試時,兩種測試方法之間的差別并不是很重要。Cobertura 還為類計算平均 McCabe 復雜度(請參閱 參考資料)。 可以深入挖掘 HTML 報告,了解特定包或者類的覆蓋率。圖 2 顯示了 圖 2. org.jaxen.function 包中的代碼覆蓋率 ![]() 進一步深入到單獨的類中,具體查看哪一行代碼沒有測試到。圖 3 顯示了 圖 3. NameFunction 類中的代碼覆蓋率 ![]()
利用 Cobertura 報告,可以找出代碼中未測試的部分并針對它們編寫測試。例如,圖 3 顯示 Jaxen 需要進行一些測試,運用 如果有許多未覆蓋的代碼,像 Cobertura 在這里報告的那樣,那么添加所有缺少的測試將會非常耗時,但也是值得的。不一定要一次完成它。您可以從被測試的最少的代碼開始,比如那些所有沒有覆蓋的包。在測試所有的包之后,就可以對每一個顯示為沒有覆蓋的類編寫一些測試代碼。對所有類進行專門測試后,還要為所有未覆蓋的方法編寫測試代碼。在測試所有方法之后,就可以開始分析對未測試的語句進行測試的必要性。 是否有一些可以測試但不應測試的內容?這取決于您問的是誰。在 JUnit FAQ 中,J. B. Rainsberger 寫到“一般的看法是:如果 自身 不會出問題,那么它會因為太簡單而不會出問題。第一個例子是
我不同意。我已經記不清在“簡單得不會出問題”的代碼中發現的 bug 的數量了。確實,一些 getter 和 setter 很簡單,不可能出問題。但是我從來就沒有辦法區分哪些方法是真的簡單得不會出錯,哪些方法只是看上去如此。編寫覆蓋像 setter 和 getter 這樣簡單方法的測試代碼并不難。為此所花的少量時間會因為在這些方法中發現未曾預料到的 bug 而得到補償。 一般來說,開始測量后,達到 90% 的測試覆蓋率是很容易的。將覆蓋率提高到 95% 或者更高就需要動一下腦筋。例如,可能需要裝載不同版本的支持庫,以測試沒有在所有版本的庫中出現的 bug。或者需要重新構建代碼,以便測試通常執行不到的部分代碼。可以對類進行擴展,讓它們的受保護方法變為公共方法,這樣就可以對這些方法進行測試。這些技巧看起來像是多此一舉,但是它們曾幫助我在一半的時間內發現更多的未發現的 bug。 并不總是可以得到完美的、100% 的代碼覆蓋率。有時您會發現,不管對代碼如何改造,仍然有一些行、方法、甚至是整個類是測試不到的。下面是您可能會遇到的挑戰的一些例子:
考慮到上面這些以及類似的情況,我認為一些極限程序員自動刪除所有未測試代碼的做法是不切實際的,并且可能具有一定的諷刺性。不能總是獲得絕對完美的測試覆蓋率并不意味著就不會有更好的覆蓋率。 然而,比執行不到的語句和方法更常見的是殘留代碼,它不再有任何作用,并且從代碼基中去掉這些代碼也不會產生任何影響。有時可以通過使用反射來訪問私有成員這樣的怪招來測試未測試的代碼。還可以為未測試的、包保護(package-protected)的代碼來編寫測試代碼,將測試類放到將要測試的類所在那個包中。但最好不要這樣做。所有不能通過發布的(公共的和受保護的)接口訪問的代碼都應刪除。執行不到的代碼不應當成為代碼基的一部分。代碼基越小,它就越容易被理解和維護。
在了解了測量代碼覆蓋率的好處后,讓我們再來討論一下如何用 Cobertura 測量代碼覆蓋率的具體細節。Cobertura 被設計成為在 Ant 中運行。現在還沒有這方面的 IDE 插件可用,不過一兩年內也許就會有了。 首先需要在 build.xml 文件中添加一個任務定義。以下這個頂級
然后,需要一個
用通常運行測試包的同一種類型的 Ant 任務運行測試。惟一的區別在于:被測量的類必須在原始類出現在類路徑中之前出現在類路徑中,而且需要將 Cobertura JAR 文件添加到類路徑中:
Jaxen 項目使用 JUnit 作為其測試框架,但是 Cobertura 是不受框架影響的。它在 TestNG、Artima SuiteRunner、HTTPUni 或者在您自己在地下室開發的系統中一樣工作得很好。 最后,
在自己的 Ant 編譯文件中加入了類似的任務后,就可以通過鍵入以下命令來生成一個覆蓋報告:
當然,如果您愿意的話,還可以改變目標任務的名稱,或者將這三項任務合并為一個目標任務。
Cobertura 是敏捷程序員工具箱中新增的一個重要工具。通過生成代碼覆蓋率的具體數值,Cobertura 將單元測試從一種藝術轉變為一門科學。它可以尋找測試覆蓋中的空隙,直接找到 bug。測量代碼覆蓋率使您可以獲得尋找并修復 bug 所需的信息,從而開發出對每個人來說都更健壯的軟件。
|
posted on 2005-12-17 11:23 GHawk 閱讀(423) 評論(0) 編輯 收藏 所屬分類: 軟件測試