单元测试相信大家都不陌生,测试先行编程(Test-First Programming)和测试驱动也不是什么新概念了。测试改进了代码质量,但这也只是针对实际测试到的那部分代码而言的。您需要有一个工具告诉您程序的哪些部分没有测试到,这样就可以针对这些部分编写测试代码并找出更多 bug。
现在,有 Cobertura (cobertura 在西班牙语是“覆盖”的意思)这个免费的 GPL 工具在 Java 领域来完成这个任务。Cobertura 通过在执行测试时,用额外的语句记录哪些行被测试到、哪些行没有被测试到,通过这种方式来度量字节码,以便对测试进行监视。然后它生成一个 HTML 或者 XML 格式的报告,指出代码中的哪些包、哪些类、哪些方法和哪些行没有测试到。可以针对这些特定的区域编写更多的测试代码,以发现所有隐藏的 bug。
先来看看生成报告的样子吧:

可以看到报告列出了每个包的行覆盖率、分支覆盖率以及复杂度。点击进去,可以看到针对这个包里头每个类的报告,进而每行代码的测试情况,以及被测试到的次数。这里是 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%。
参考资料

暂无评论