Ant+JUnit+Cobertura执行测试用例时,应注意的有关问题(以Apache POI为例)
这两天想做些实验,研究了半天Cobertura,发现还是不能满足我的需求。不过也借此机会总结一下Ant+JUnit+Cobertura执行测试用例的经验。主要是参考了下面两篇文章:
http://aofengblog.blog.163.com/blog/static/6317021201312763630878/
http://www.ibm.com/developerworks/cn/java/j-cobertura/
其实这两篇文章已经说得很清楚了,我再把一些细节总结一下(以Apache POI自带的测试用例为例):
在这里:http://cobertura.github.io/cobertura/,有Cobertura的最新下载链接,下载并解压后,将cobertura-2.0.3.jar和lib里的所有JAR包,可以放到一个新的文件夹中,例如:cobertura-lib,而后,在build.xml把这些JAR包包含进来:
<path id="cobertura.classpath"> <fileset dir="cobertura-lib"> <include name="*.jar"/> </fileset> </path>
而后定义一些property,这些可以因人而异,我这里列出来是为后面叙述方便:
<property name="target.cover-test.dir" location="${main.output.dir}/cover-test" /> <property name="target.report.dir" location="${basedir}/report" /> <property name="target.unit-test-report.dir" location="${target.report.dir}/unit-test" /> <property name="target.cover-test-report.dir" location="${target.report.dir}/cover-test" />
要使用cobertura,其实也就分三步:1.用cobertura插桩(instrument),2.执行经过插桩的代码,3.生成报告。所以下面从这三个步骤介绍:
首先进行插桩(其实cobertura也是基于ASM进行插桩的):
<taskdef classpathref="cobertura.classpath" resource="tasks.properties" /> <target name="cover-instrument" depends="compile"> <mkdir dir="${target.cover-test.dir}"/> <cobertura-instrument todir="${target.cover-test.dir}"> <fileset dir="${main.output.dir}"> <include name="**/**.class" /> </fileset> </cobertura-instrument> </target>
taskdef这行,是Ant使用第三方任务的方法,如果第三方提供自己的任务,都会事先写好properties供他人使用。该properties文件一般存在jar包中。如果我们将cobertura-2.0.3.jar解压,就可以看到tasks.properties这样一个文件:
cobertura-instrument=net.sourceforge.cobertura.ant.InstrumentTask cobertura-merge=net.sourceforge.cobertura.ant.MergeTask cobertura-report=net.sourceforge.cobertura.ant.ReportTask cobertura-check=net.sourceforge.cobertura.ant.CheckTask
其含义也很简单。cover-instrument这个Target的目的就是将class文件进行二次编译,插入一些ASM的监控代码。
然后执行测试用例(这里我都是以Apache POI为例进行说明的,所以里面可能有些Project Specific的配置):
<target name="cover-test" depends="cover-instrument"> <mkdir dir="${target.cover-test-report.dir}"/> <junit printsummary="on" haltonerror="off" haltonfailure="off" fork="on"> <classpath location="cobertura-lib/cobertura-2.0.3.jar"/> <classpath path="${target.cover-test.dir}" /> <classpath refid="test.classpath"/> <formatter type="plain"/> <syspropertyset refid="junit.properties"/> <jvmarg value="${poi.test.locale}"/> <batchtest todir="${main.reports.test}"> <fileset dir="${main.src.test}"> <include name="**/${testpattern}.java"/> <exclude name="**/All*Tests.java"/> <exclude name="**/TestUnfixedBugs.java"/> <exclude name="**/TestcaseRecordInputStream.java"/> </fileset> </batchtest> </junit> </target>
需要注意的问题包括:这里需要显式地把cobertura的jar包包含进来,另外,需要将插桩以后的class文件放到classpath的开头处,其他和正常执行junit一样。
最后,生成覆盖率报告:
<target name="cover-report" depends="cover-test"> <cobertura-report srcdir="${main.src}" destdir="${target.cover-test-report.dir}" /> </target>
需要注意的是,srcdir指定的是源代码文件夹。
就简单总结这么多。