Cobertura是一个基于jcoverage的免费Java工具,它能够显示哪一部分代码被你的测试所覆盖,并可生成HTML或XML报告. 本文将介绍如何在项目中使用cobertura来测量单元测试的代码覆盖情况.

首先创建一个Java项目,本文以Eclipse为例:

项目名: CodeCoverageTest

结构图如下:



接下,创建一个Ant构建配置文件,帮我们实现自动化的编译,单元测试以及cobertura来测量单元测试的代码覆盖情况。

Ant的 build.xml文件内容如下:

Java代码   收藏代码

 

 
   
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2.   2    
  3.   3 <project name="cobertura.examples.basic" default="coverage" basedir=".">   
  4.   4        
  5.   5     <!-- 引用 build.properties文件 配置路径信息-->   
  6.   6     <property file="build.properties" />   
  7.   7    
  8.   8     <!-- 设置 cobertura路径 -->   
  9.   9     <path id="cobertura.classpath">   
  10.  10         <fileset dir="${cobertura.dir}">   
  11.  11             <include name="cobertura.jar" />   
  12.  12             <include name="lib/**/*.jar" />   
  13.  13         </fileset>   
  14.  14     </path>   
  15.  15    
  16.  16     <!-- 配置 cobatura ant 扩展任务 -->   
  17.  17     <taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>   
  18.  18    
  19.  19     <target name="init">   
  20.  20         <mkdir dir="${classes.dir}" />   
  21.  21         <mkdir dir="${instrumented.dir}" />   
  22.  22         <mkdir dir="${reports.xml.dir}" />   
  23.  23         <mkdir dir="${reports.html.dir}" />   
  24.  24         <mkdir dir="${coverage.xml.dir}" />   
  25.  25         <mkdir dir="${coverage.html.dir}" />   
  26.  26     </target>   
  27.  27    
  28.  28     <!-- 编译源代码 -->   
  29.  29     <target name="compile" depends="init">   
  30.  30         <javac srcdir="${src.dir}:${test.dir}:${src.conf.dir}:${test.conf.dir}" destdir
  31. ="${classes.dir}" debug="yes">   
  32.  31             <classpath refid="cobertura.classpath" />   
  33.  32         </javac>   
  34.  33     </target>   
  35.  34    
  36.  35     <target name="instrument" depends="init,compile">   
  37.  36         <!--   
  38.  37             Remove the coverage data file and any old instrumentation.   
  39.  38         -->   
  40.  39         <delete file="cobertura.ser"/>   
  41.  40         <delete dir="${instrumented.dir}" />   
  42.  41    
  43.  42         <!--   
  44.  43             Instrument the application classes, writing the   
  45.  44             instrumented classes into ${build.instrumented.dir}.   
  46.  45         -->   
  47.  46         <cobertura-instrument todir="${instrumented.dir}">   
  48.  47             <!--   
  49.  48                 The following line causes instrument to ignore any   
  50.  49                 source line containing a reference to log4j, for the   
  51.  50                 purposes of coverage reporting.   
  52.  51             -->   
  53.  52             <ignore regex="org.apache.log4j.*" />   
  54.  53    
  55.  54             <fileset dir="${classes.dir}">   
  56.  55                 <!--   
  57.  56                     Instrument all the application classes, but   
  58.  57                     don't instrument the test classes.   
  59.  58                 -->   
  60.  59                 <include name="**/*.class" />   
  61.  60                 <exclude name="**/*Test.class" />   
  62.  61             </fileset>   
  63.  62         </cobertura-instrument>   
  64.  63     </target>   
  65.  64    
  66.  65     <!-- 单元测试 -->   
  67.  66     <target name="test" depends="init,compile">   
  68.  67         <junit fork="yes" dir="${basedir}" failureProperty="test.failed">   
  69.  68             <!--   
  70.  69                 Note the classpath order: instrumented classes are before the   
  71.  70                 original (uninstrumented) classes.  This is important.   
  72.  71             -->   
  73.  72             <classpath location="${instrumented.dir}" />   
  74.  73             <classpath location="${classes.dir}" />   
  75.  74    
  76.  75             <!--   
  77.  76                 The instrumented classes reference classes used by the   
  78.  77                 Cobertura runtime, so Cobertura and its dependencies   
  79.  78                 must be on your classpath.   
  80.  79             -->   
  81.  80             <classpath refid="cobertura.classpath" />   
  82.  81    
  83.  82             <formatter type="xml" />   
  84.  83             <test name="${testcase}" todir="${reports.xml.dir}" if="testcase" />   
  85.  84             <batchtest todir="${reports.xml.dir}" unless="testcase">   
  86.  85                 <fileset dir="${test.dir}">   
  87.  86                     <include name="**/*Test.java" />   
  88.  87                 </fileset>   
  89.  88                 <fileset dir="${src.dir}">   
  90.  89                     <include name="**/*Test.java" />   
  91.  90                 </fileset>                   
  92.  91             </batchtest>   
  93.  92         </junit>   
  94.  93    
  95.  94         <junitreport todir="${reports.xml.dir}">   
  96.  95             <fileset dir="${reports.xml.dir}">   
  97.  96                 <include name="TEST-*.xml" />   
  98.  97             </fileset>   
  99.  98             <report format="frames" todir="${reports.html.dir}" />   
  100.  99         </junitreport>   
  101. 100     </target>   
  102. 101    
  103. 102     <target name="coverage-check">   
  104. 103         <cobertura-check branchrate="34" totallinerate="100" />   
  105. 104     </target>   
  106. 105    
  107. 106     <!-- 生成 coverage xml格式报告 -->   
  108. 107     <target name="coverage-report">   
  109. 108         <!--   
  110. 109             Generate an XML file containing the coverage data using   
  111. 110             the "srcdir" attribute.   
  112. 111         -->   
  113. 112         <cobertura-report srcdir="${src.dir}" destdir="${coverage.xml.dir}" format=
  114. "xml" />   
  115. 113     </target>   
  116. 114    
  117. 115     <!-- 生成 coverage html格式报告 -->   
  118. 116     <target name="alternate-coverage-report">   
  119. 117         <!--   
  120. 118             Generate a series of HTML files containing the coverage   
  121. 119             data in a user-readable form using nested source filesets.   
  122. 120         -->   
  123. 121         <cobertura-report destdir="${coverage.html.dir}">   
  124. 122             <fileset dir="${src.dir}">   
  125. 123                 <include name="**/*.java"/>   
  126. 124             </fileset>   
  127. 125         </cobertura-report>   
  128. 126     </target>   
  129. 127    
  130. 128     <target name="clean" description="Remove all files created by the build/test 
  131. process.">   
  132. 129         <delete dir="${classes.dir}" />   
  133. 130         <delete dir="${instrumented.dir}" />   
  134. 131         <delete dir="${reports.dir}" />   
  135. 132         <delete file="cobertura.log" />   
  136. 133         <delete file="cobertura.ser" />   
  137. 134     </target>   
  138. 135    
  139. 136     <target name="coverage" depends="compile,instrument,test,coverage-report,
  140. alternate-coverage-report"  description="Compile, instrument ourself,
  141.  run the tests and generate JUnit and coverage reports."/>   
  142. 137    
  143. 138 </project>   
  144. 139    


build.properties文件

 
  
  1. # The source code for the examples can be found in this directory    
  2. src.dir=../src/java    
  3. src.conf.dir=../src/conf    
  4. test.dir=../test/java    
  5. test.conf.dir=../src/conf    
  6.     
  7. # The path to cobertura.jar    
  8. coberturacoberturacobertura.dir=cobertura    
  9.     
  10. # Classes generated by the javac compiler are deposited in this directory    
  11. classes.dir=../bin    
  12.     
  13. # Instrumented classes are deposited into this directory    
  14. instrumentedinstrumentedinstrumented.dir=instrumented    
  15.     
  16. # All reports go into this directory    
  17. reportsreportsreports.dir=reports    
  18.     
  19. # Unit test reports from JUnit are deposited into this directory    
  20. reports.xml.dir=${reports.dir}/junit-xml    
  21. reports.html.dir=${reports.dir}/junit-html    
  22.     
  23. # Coverage reports are deposited into these directories    
  24. coverage.xml.dir=${reports.dir}/cobertura-xml    
  25. coverage.html.dir=${reports.dir}/cobertura-html    

编写示例代码
Hello.java

Java代码   收藏代码
 
 
    
  1. package com.xmatthew.practise.cobertura;    
  2.       
  3.   public class Hello {    
  4.       
  5.       public String birthday(String name) {    
  6.           return "happy birthday to " + name;    
  7.       }    
  8.          
  9.       public String christmas(String name) {    
  10.          return "merry christmas " + name;    
  11.      }    
  12.          
  13.  }    


编写测试Hello.java的测试类,进行单元测试
HelloTest.java

Java代码   收藏代码
 
 
    
  1. package com.xmatthew.practise.cobertura;   
  2.     
  3.  import junit.framework.Assert;   
  4.  import junit.framework.TestCase;   
  5.     
  6.  public class HelloTest extends TestCase {   
  7.         
  8.      private Hello hello;   
  9.     
  10.      protected void setUp() throws Exception {   
  11.          hello = new Hello();   
  12.      }   
  13.     
  14.      protected void tearDown() throws Exception {   
  15.          hello = null;   
  16.      }   
  17.     
  18.      public void testBirthday() {   
  19.          String expected = "happy birthday to matt";   
  20.          Assert.assertEquals(expected, hello.birthday("matt"));   
  21.      }   
  22.     
  23.      public void testChristmas() {   
  24.          String expected = "merry christmas matt";   
  25.          Assert.assertEquals(expected, hello.christmas("matt"));   
  26.      }   
  27.     
  28.  }  


接下来,我们运行 Cobertura来进行测试
运行 Cobertura,测试在Eclipse运行时,要在Ant插件的运行类库环境中加入cobertura相关类库。



查看运行结果报告:

JUnit报告

Cobertura报告




    到目前已经完成整个项目的基于Ant进行编译,测试以及生成Cobertura测试报告的开发IDE环境。这个项目框架足以应用日常的开发需求。

Cobertura官网地址: http://cobertura.sourceforge.net/