不要漏掉測(cè)量單元測(cè)試包和類本身。我不止一次注意到,某些個(gè)測(cè)試方法或者類沒有被測(cè)試包真正運(yùn)行。通常這表明名稱規(guī)范中存在問題(比如將一個(gè)方法命名為 tesSomeReallyComplexCondition,而不是將其命名為 testSomeReallyComplexCondition),或者忘記將一個(gè)類添加到主 suite() 方法中。在其他情況下,未預(yù)期的條件導(dǎo)致跳過(guò)了測(cè)試方法中的代碼。不管是什么情況,都是雖然已經(jīng)編寫了測(cè)試代碼,但沒有真正運(yùn)行它。JUnit 不會(huì)告訴您它沒有像您所想的那樣運(yùn)行所有測(cè)試,但是 Cobertura 會(huì)告訴您。找出了未運(yùn)行的測(cè)試后,改正它一般很容易。
運(yùn)行 Cobertura
在了解了測(cè)量代碼覆蓋率的好處后,讓我們?cè)賮?lái)討論一下如何用 Cobertura 測(cè)量代碼覆蓋率的具體細(xì)節(jié)。Cobertura 被設(shè)計(jì)成為在 Ant 中運(yùn)行,F(xiàn)在還沒有這方面的 IDE 插件可用,不過(guò)一兩年內(nèi)也許會(huì)有了。
首先需要在 build.xml 文件中添加一個(gè)任務(wù)定義。以下這個(gè) taskdef 元素將 cobertura.jar 文件限定在當(dāng)前工作目錄中:
<taskdef classpath="cobertura.jar" resource="tasks.properties" />
然后,需要一個(gè) cobertura-instrument 任務(wù),該任務(wù)將在已經(jīng)編譯好的類文件中添加日志代碼。todir 屬性指定將測(cè)量類放到什么地方。fileset 子元素指定測(cè)量哪些 .class 文件:
<target name="instrument">
<cobertura-instrument todir="target/instrumented-classes">
<fileset dir="target/classes">
<include name="**/*.class"/>
</fileset>
</cobertura-instrument>
</target>
用通常運(yùn)行測(cè)試包的同一種類型的 Ant 任務(wù)運(yùn)行測(cè)試。惟一的區(qū)別在于:被測(cè)量的類必須在原始類出現(xiàn)在類路徑中之前出現(xiàn)在類路徑中,而且需要將 Cobertura JAR 文件添加到類路徑中:
<target name="cover-test" depends="instrument">
<mkdir dir="${testreportdir}" />
<junit dir="./" failureproperty="test.failure" printSummary="yes"
fork="true" haltonerror="true">
<!-- Normally you can create this task by copying your existing JUnit
target, changing its name, and adding these next two lines.
You may need to change the locations to point to wherever
you've put the cobertura.jar file and the instrumented classes. -->
<classpath location="cobertura.jar"/>
<classpath location="target/instrumented-classes"/>
<classpath>
<fileset dir="${libdir}">
<include name="*.jar" />
</fileset>
<pathelement path="${testclassesdir}" />
<pathelement path="${classesdir}" />
</classpath>
<batchtest todir="${testreportdir}">
<fileset dir="src/java/test">
<include name="**/*Test.java" />
<include name="org/jaxen/javabean/*Test.java" />
</fileset>
</batchtest>
</junit>
</target>>
Jaxen 項(xiàng)目使用 JUnit 作為其測(cè)試框架,但是 Cobertura 是不受框架影響的。它在 TestNG、Artima SuiteRunner、HTTPUni 或者在您自己在地下室開發(fā)的系統(tǒng)中一樣工作得很好。
后,cobertura-report 任務(wù)生成本文開始部分看到的那個(gè) HTML 文件:
<target name="coverage-report" depends="cover-test">
<cobertura-report srcdir="src/java/main" destdir="cobertura"/>
</target>
srcdir 屬性指定原始的 .java 源代碼在什么地方。destdir 屬性指定 Cobertura 放置輸出 HTML 的那個(gè)目錄的名稱。
在自己的 Ant 編譯文件中加入了類似的任務(wù)后,可以通過(guò)鍵入以下命令來(lái)生成一個(gè)覆蓋報(bào)告:
% ant instrument
% ant cover-test
% ant coverage-report
當(dāng)然,如果您愿意的話,還可以改變目標(biāo)任務(wù)的名稱,或者將這三項(xiàng)任務(wù)合并為一個(gè)目標(biāo)任務(wù)。
結(jié)束語(yǔ)
Cobertura 是敏捷程序員工具箱中新增的一個(gè)重要工具。通過(guò)生成代碼覆蓋率的具體數(shù)值,Cobertura 將單元測(cè)試從一種藝術(shù)轉(zhuǎn)變?yōu)橐婚T科學(xué)。它可以尋找測(cè)試覆蓋中的空隙,直接找到 bug。測(cè)量代碼覆蓋率使您可以獲得尋找并修復(fù) bug 所需的信息,從而開發(fā)出對(duì)每個(gè)人來(lái)說(shuō)都更健壯的軟件。