Cobertura是一个基于jcoverage的免费Java工具,它能够显示哪一部分代码被你的 测试所覆盖,并可生成HTML或XML报告。本文将介绍如何在项目中使用cobertura来测量 单元测试的代码覆盖情况。
首先创建一个Java项目,本文以Eclipse为例:
项目名:CodeCoverageTest
结构图如下:
接下,创建一个Ant构建配置文件,帮我们实现自动化的编译,单元测试以及cobertura来测量单元测试的代码覆盖情况。
Ant的 build.xml文件内容如下:
Java代码
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <project name="cobertura.examples.basic" default="coverage" basedir="."> 4 5 <!-- 引用 build.properties文件 配置路径信息--> 6 <property file="build.properties" /> 7 8 <!-- 设置 cobertura路径 --> 9 <path id="cobertura.classpath"> 10 <fileset dir="${cobertura.dir}"> 11 <include name="cobertura.jar" /> 12 <include name="lib/**/*.jar" /> 13 </fileset> 14 </path> 15 16 <!-- 配置 cobatura ant 扩展任务 --> 17 <taskdef classpathref="cobertura.classpath" resource="tasks.properties"/> 18 19 <target name="init"> 20 <mkdir dir="${classes.dir}" /> 21 <mkdir dir="${instrumented.dir}" /> 22 <mkdir dir="${reports.xml.dir}" /> 23 <mkdir dir="${reports.html.dir}" /> 24 <mkdir dir="${coverage.xml.dir}" /> 25 <mkdir dir="${coverage.html.dir}" /> 26 </target> 27 28 <!-- 编译源代码 --> 29 <target name="compile" depends="init"> 30 <javac srcdir="${src.dir}:${test.dir}:${src.conf.dir}:${test.conf.dir}" destdir="${classes.dir}" debug="yes"> 31 <classpath refid="cobertura.classpath" /> 32 </javac> 33 </target> 34 35 <target name="instrument" depends="init,compile"> 36 <!-- 37 Remove the coverage data file and any old instrumentation. 38 --> 39 <delete file="cobertura.ser"/> 40 <delete dir="${instrumented.dir}" /> 41 42 <!-- 43 Instrument the application classes, writing the 44 instrumented classes into ${build.instrumented.dir}. 45 --> 46 <cobertura-instrument todir="${instrumented.dir}"> 47 <!-- 48 The following line causes instrument to ignore any 49 source line containing a reference to log4j, for the 50 purposes of coverage reporting. 51 --> 52 <ignore regex="org.apache.log4j.*" /> 53 54 <fileset dir="${classes.dir}"> 55 <!-- 56 Instrument all the application classes, but 57 don't instrument the test classes. 58 --> 59 <include name="**/*.class" /> 60 <exclude name="**/*Test.class" /> 61 </fileset> 62 </cobertura-instrument> 63 </target> 64 65 <!-- 单元测试 --> 66 <target name="test" depends="init,compile"> 67 <junit fork="yes" dir="${basedir}" failureProperty="test.failed"> 68 <!-- 69 Note the classpath order: instrumented classes are before the 70 original (uninstrumented) classes. This is important. 71 --> 72 <classpath location="${instrumented.dir}" /> 73 <classpath location="${classes.dir}" /> 74 75 <!-- 76 The instrumented classes reference classes used by the 77 Cobertura runtime, so Cobertura and its dependencies 78 must be on your classpath. 79 --> 80 <classpath refid="cobertura.classpath" /> 81 82 <formatter type="xml" /> 83 <test name="${testcase}" todir="${reports.xml.dir}" if="testcase" /> 84 <batchtest todir="${reports.xml.dir}" unless="testcase"> 85 <fileset dir="${test.dir}"> 86 <include name="**/*Test.java" /> 87 </fileset> 88 <fileset dir="${src.dir}"> 89 <include name="**/*Test.java" /> 90 </fileset> 91 </batchtest> 92 </junit> 93 94 <junitreport todir="${reports.xml.dir}"> 95 <fileset dir="${reports.xml.dir}"> 96 <include name="TEST-*.xml" /> 97 </fileset> 98 <report format="frames" todir="${reports.html.dir}" /> 99 </junitreport> 100 </target> 101 102 <target name="coverage-check"> 103 <cobertura-check branchrate="34" totallinerate="100" /> 104 </target> 105 106 <!-- 生成 coverage xml格式报告 --> 107 <target name="coverage-report"> 108 <!-- 109 Generate an XML file containing the coverage data using 110 the "srcdir" attribute. 111 --> 112 <cobertura-report srcdir="${src.dir}" destdir="${coverage.xml.dir}" format="xml" /> 113 </target> 114 115 <!-- 生成 coverage html格式报告 --> 116 <target name="alternate-coverage-report"> 117 <!-- 118 Generate a series of HTML files containing the coverage 119 data in a user-readable form using nested source filesets. 120 --> 121 <cobertura-report destdir="${coverage.html.dir}"> 122 <fileset dir="${src.dir}"> 123 <include name="**/*.java"/> 124 </fileset> 125 </cobertura-report> 126 </target> 127 128 <target name="clean" description="Remove all files created by the build/test process."> 129 <delete dir="${classes.dir}" /> 130 <delete dir="${instrumented.dir}" /> 131 <delete dir="${reports.dir}" /> 132 <delete file="cobertura.log" /> 133 <delete file="cobertura.ser" /> 134 </target> 135 136 <target name="coverage" depends="compile,instrument,test,coverage-report,alternate-coverage-report" description="Compile, instrument ourself, run the tests and generate JUnit and coverage reports."/> 137 138 </project>
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <project name="cobertura.examples.basic" default="coverage" basedir="."> 4 5 <!-- 引用 build.properties文件 配置路径信息--> 6 <property file="build.properties" /> 7 8 <!-- 设置 cobertura路径 --> 9 <path id="cobertura.classpath"> 10 <fileset dir="${cobertura.dir}"> 11 <include name="cobertura.jar" /> 12 <include name="lib/**/*.jar" /> 13 </fileset> 14 </path> 15 16 <!-- 配置 cobatura ant 扩展任务 --> 17 <taskdef classpathref="cobertura.classpath" resource="tasks.properties"/> 18 19 <target name="init"> 20 <mkdir dir="${classes.dir}" /> 21 <mkdir dir="${instrumented.dir}" /> 22 <mkdir dir="${reports.xml.dir}" /> 23 <mkdir dir="${reports.html.dir}" /> 24 <mkdir dir="${coverage.xml.dir}" /> 25 <mkdir dir="${coverage.html.dir}" /> 26 </target> 27 28 <!-- 编译源代码 --> 29 <target name="compile" depends="init"> 30 <javac srcdir="${src.dir}:${test.dir}:${src.conf.dir}:${test.conf.dir}" destdir="${classes.dir}" debug="yes"> 31 <classpath refid="cobertura.classpath" /> 32 </javac> 33 </target> 34 35 <target name="instrument" depends="init,compile"> 36 <!-- 37 Remove the coverage data file and any old instrumentation. 38 --> 39 <delete file="cobertura.ser"/> 40 <delete dir="${instrumented.dir}" /> 41 42 <!-- 43 Instrument the application classes, writing the 44 instrumented classes into ${build.instrumented.dir}. 45 --> 46 <cobertura-instrument todir="${instrumented.dir}"> 47 <!-- 48 The following line causes instrument to ignore any 49 source line containing a reference to log4j, for the 50 purposes of coverage reporting. 51 --> 52 <ignore regex="org.apache.log4j.*" /> 53 54 <fileset dir="${classes.dir}"> 55 <!-- 56 Instrument all the application classes, but 57 don't instrument the test classes. 58 --> 59 <include name="**/*.class" /> 60 <exclude name="**/*Test.class" /> 61 </fileset> 62 </cobertura-instrument> 63 </target> 64 65 <!-- 单元测试 --> 66 <target name="test" depends="init,compile"> 67 <junit fork="yes" dir="${basedir}" failureProperty="test.failed"> 68 <!-- 69 Note the classpath order: instrumented classes are before the 70 original (uninstrumented) classes. This is important. 71 --> 72 <classpath location="${instrumented.dir}" /> 73 <classpath location="${classes.dir}" /> 74 75 <!-- 76 The instrumented classes reference classes used by the 77 Cobertura runtime, so Cobertura and its dependencies 78 must be on your classpath. 79 --> 80 <classpath refid="cobertura.classpath" /> 81 82 <formatter type="xml" /> 83 <test name="${testcase}" todir="${reports.xml.dir}" if="testcase" /> 84 <batchtest todir="${reports.xml.dir}" unless="testcase"> 85 <fileset dir="${test.dir}"> 86 <include name="**/*Test.java" /> 87 </fileset> 88 <fileset dir="${src.dir}"> 89 <include name="**/*Test.java" /> 90 </fileset> 91 </batchtest> 92 </junit> 93 94 <junitreport todir="${reports.xml.dir}"> 95 <fileset dir="${reports.xml.dir}"> 96 <include name="TEST-*.xml" /> 97 </fileset> 98 <report format="frames" todir="${reports.html.dir}" /> 99 </junitreport> 100 </target> 101 102 <target name="coverage-check"> 103 <cobertura-check branchrate="34" totallinerate="100" /> 104 </target> 105 106 <!-- 生成 coverage xml格式报告 --> 107 <target name="coverage-report"> 108 <!-- 109 Generate an XML file containing the coverage data using 110 the "srcdir" attribute. 111 --> 112 <cobertura-report srcdir="${src.dir}" destdir="${coverage.xml.dir}" format="xml" /> 113 </target> 114 115 <!-- 生成 coverage html格式报告 --> 116 <target name="alternate-coverage-report"> 117 <!-- 118 Generate a series of HTML files containing the coverage 119 data in a user-readable form using nested source filesets. 120 --> 121 <cobertura-report destdir="${coverage.html.dir}"> 122 <fileset dir="${src.dir}"> 123 <include name="**/*.java"/> 124 </fileset> 125 </cobertura-report> 126 </target> 127 128 <target name="clean" description="Remove all files created by the build/test process."> 129 <delete dir="${classes.dir}" /> 130 <delete dir="${instrumented.dir}" /> 131 <delete dir="${reports.dir}" /> 132 <delete file="cobertura.log" /> 133 <delete file="cobertura.ser" /> 134 </target> 135 136 <target name="coverage" depends="compile,instrument,test,coverage-report,alternate-coverage-report" description="Compile, instrument ourself, run the tests and generate JUnit and coverage reports."/> 137 138 </project> |
build.properties文件:
Java代码
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 cobertura.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 instrumented.dir=instrumented 15 16 All reports go into this directory 17 reports.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 26
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 cobertura.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 instrumented.dir=instrumented 15 16 All reports go into this directory 17 reports.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 26 |
编写示例代码:
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 }
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 } 29
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 } 29 |
接下来,我们运行 Cobertura来进行测试。
运行 Cobertura,测试在Eclipse运行时,要在Ant插件的运行类库环境中加入cobertura相关类库。
查看运行结果报告
JUnit报告:
Cobertura报告:
到目前已经完成整个项目的基于Ant进行编译,测试以及生成Cobertura测试报告的开发IDE环境。这个项目框架足以应用日常的开发需求。
Cobertura官网地址: http://cobertura./
|