Monday, September 01, 2008

用 Cobertura 测量测试覆盖率

单元测试相信大家都不陌生,测试先行编程(Test-First Programming)和测试驱动也不是什么新概念了。测试改进了代码质量,但这也只是针对实际测试到的那部分代码而言的。您需要有一个工具告诉您程序的哪些部分没有测试到,这样就可以针对这些部分编写测试代码并找出更多 bug。

现在,有 Cobertura (cobertura 在西班牙语是“覆盖”的意思)这个免费的 GPL 工具在 Java 领域来完成这个任务。Cobertura 通过在执行测试时,用额外的语句记录哪些行被测试到、哪些行没有被测试到,通过这种方式来度量字节码,以便对测试进行监视。然后它生成一个 HTML 或者 XML 格式的报告,指出代码中的哪些包、哪些类、哪些方法和哪些行没有测试到。可以针对这些特定的区域编写更多的测试代码,以发现所有隐藏的 bug。

先来看看生成报告的样子吧:

Cobertura 报告示例(点击放大)


可以看到报告列出了每个包的行覆盖率、分支覆盖率以及复杂度。点击进去,可以看到针对这个包里头每个类的报告,进而每行代码的测试情况,以及被测试到的次数。这里是 Cobertura 官方网站上给出的一个报告的 Sample。

在使用上,Cobertura 支持命令行操作,也可以结合到 Ant 任务。当然首先要定义任务:
<property name="cobertura.dir" value="C:/javastuff/cobertura" />

<path id="cobertura.classpath">
<fileset dir="${cobertura.dir}">
<include name="cobertura.jar" />
<include name="lib/**/*.jar" />
</fileset>
</path>

<taskdef classpathref="cobertura.classpath" resource="tasks.properties" />

然后,就可以用 cobertura-instrument 任务来统计测试目标:
<delete file="cobertura.ser" />

<cobertura-instrument todir="${instrumented.dir}">
<ignore regex="org.apache.log4j.*" />
<fileset dir="${classes.dir}">
<include name="**/*.class" />
<exclude name="**/*Test.class" />
</fileset>
<fileset dir="${guiclasses.dir}">
<include name="**/*.class" />
<exclude name="**/*Test.class" />
</fileset>
<fileset dir="${jars.dir}">
<include name="my-simple-plugin.jar" />
</fileset>
</cobertura-instrument>

之后,运行 Junit 测试(重要的部分用蓝色标出):
<junit fork="yes" dir="${basedir}" failureProperty="test.failed">
<!--
指定覆盖率统计的数据文件名,以下为默认值
-->
<sysproperty key="net.sourceforge.cobertura.datafile"
file="${basedir}/cobertura.ser" />


<!--
注意 classpath 的顺序:被处理过的 class 路径在为处理的
class 路径之前。这很重要!
-->
<classpath location="${instrumented.dir}" />
<classpath location="${classes.dir}" />

<!--
被处理过的 class 会在 Cobertura 运行时引用 Cobertura
的类库,因此这些类也必须在我们的 classpath 中。
-->
<classpath refid="cobertura_classpath" />

<formatter type="xml" />
<test name="${testcase}" todir="${reports.xml.dir}" if="testcase" />
<batchtest todir="${reports.xml.dir}" unless="testcase">
<fileset dir="${src.dir}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>

最后,我们可以用 cobertura-report 任务来输出 HTML 格式或者 XML 格式的报告:
<cobertura-report format="html" destdir="${coveragereport.dir}"
srcdir="${src.dir}" />

也可以有更复杂的要求:
<cobertura-report format="html" destdir="${coveragereport.dir}" >
<fileset dir="${src.dir}">
<include name="**/*.java" />
<exclude name="**/*Stub.java" />
</fileset>
<fileset dir="${guisrc.dir}">
<include name="**/*.java" />
<exclude name="**/*RB.java" />
</fileset>
</cobertura-report>

另外,还可以用 cobertura-check 任务来检查统计出来的覆盖率是否达到预先的期望,如果没有达到则使得整个 Ant 任务失败;以及 cobertura-merge 任务用来合并多个测试的统计数据文件。

要特别注意的是,在这个 Ant 任务中,一定要保证数据文件 cobertura.ser 每次都被更新,并且在 instrument 的任务和后面做 Junit 的过程中,两者的路径一致,否则可能导致在输出的报告中,所有的测试结果都是 100% 或者 0%。

参考资料

7 comments:

Unknown said...

louis vuitton handbags
burberry scarf
ray ban sunglasses outlet
michael kors
cheap uggs
cheap oakleys
abercrombie fitch
ugg boots
tory burch flats
lv outlet
tods outlet
michael kors handbags
michael kors outlet online
ghd flat iron
coach outlet
coach factory online
prada handbags
lebron 11
canada goose jacket
ray ban outlet
christian louboutin
chanel handbags
coach outlet
polo outlet
michael kors outlet online
ray ban canada
coach factory outlet
20150311huangqihang

chenlili said...

chenlili20160629
michael kors outlet
coach factory outlet
air jordans
oakley outlet
kobe 11
nike running shoes for women
cheap air jordans
michael kors outlet clearance
ralph lauren
gucci outlet
nike air max 90
ralph lauren outlet
air jordans
retro jordans 13
montblanc
vans shoes
jordan retro 11
hollister outlet
toms shoes
ralph lauren
michael kors handbags
true religion sale
ray ban sunglasses
tory burch outlet online
gucci belts
marc jacobs handbags
coach outlet store online
louis vuitton outlet online
timberlands
oakley sunglasses
hollister clothing
kobe shoes
ray bans
ray ban sunglasses
michael kors outlet online
replica rolex watches
true religion outlet

Unknown said...

valentino shoes on sale
fitflops
true religion outlet
pandora charms
pandora charms
nike air max
michael kors purses
rolex submariner
nike air force white
versace shoes
tiffany and co
ray bans
cheap ugg sale
oakley sunglasses
coach outlet
kate spade handbags
adidas superstar
hollister sale
polo ralph lauren uk
moncler outlet store
mizuno running shoes
discount oakley sunglasses
prada outlet
fitflop uk
polo ralph lauren
zhenwei20160721

chenmeinv0 said...

cheap ray ban sunglasses
ray ban wayfarer
uggs uk
louis vuitton handbags
uggs on sale
ralph lauren outlet
louis vuitton
toms shoes uk
coach outlet store online clearances
pandora charms
2016.11.14xukaimin

chenmeinv0 said...

michael kors outlet
cheap toms shoes
christian louboutin pas cher
ugg australia
red bottom shoes
ray ban sunglasses
canada goose
coach handbags
uggs pas cher
cheap ugg boots
hzx20170206

Unknown said...

mulberry handbags
fitflops sale clearance
cheap oakley sunglasses
oakley sunglasses
ralph lauren polo
nike shoes uk
fitflops outlet
pandora charms sale clearance
cartier watches
nike outlet store
chanyuan2017.04.01

xjd7410@gmail.com said...

20170513 junda
yeezy boost
burberry canada
cheap jordan shoes
rolex watches for sale
gucci outlet online
ralph lauren outlet
coach factory outlet
fitflops sale clearance
polo outlet
michael kors handbags outlet