场景1:单模块 或 多模块独立统计(即每个模块只使用自己的单元测试统计覆盖率)
使用maven中集成的插件:cobertura-maven-plugin
cobertura-maven-plugin:用于校验单元测试用例覆盖率,可以生成单元测试覆盖率报告
示例:
新建一个maven工程module-product,目录结构如下:
Function.java 文件内容:
package com.function;
public class Function {
public int add (int a, int b) {
return a + b;
}
}
FunctionTest.java 文件内容:
package com.function;
import org.junit.Test;
import junit.framework.Assert;
public class FunctionTest {
@Test
public void shouldCalculateFibonacci() {
Function function = new Function();
int actual = function.add(1, 2);
Assert.assertEquals(3, actual);
}
}
pom.xml文件添加插件:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.function</groupId>
<artifactId>module-cobertura</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
module-product 根目录执行maven命令:mvn cobertura:cobertura
在\module-project\target\site\cobertura目录,打开index.html就是测试用例的覆盖率报告,如下图:
场景2:多模块maven项目(需要跨模块统计)
在多模块项目中,出于项目分解管理或配置文件的原因,我们可能会把源代码放在一个模块,测试代码放在另一个模块;或者某个模块没有单元测试,被其他模块的单元测试所覆盖。而maven的模块是一个执行完再执行另一个,导致cobetura的代码覆盖率统计出现问题。
maven的项目结构是固定的,一个java模块生成一个target文件,各模块是隔离的,因此无法跨模块比对运行的测试类和源代码文件。
使用Ant+maven的方式可以解决上面的问题。Ant与maven相比,它的灵活在于可以让用户自己指定源码的位置和编译后字节码的存放位置,如此又可以达到单模块maven项目的效果。
示例:
构建maven工程modules-project,其中包含两个maven项目:module-a和module-b
module-a:包括功能代码FcuntionA.java,功能为加法运算
包括测试代码FcuntionTest.java,功能为测试FcuntionA.java和FcuntionB.java
module-b:包括功能代码FcuntionB.java,功能为乘法运算
代码结构如下:
modules-project
modules-project的pom.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.function</groupId>
<artifactId>parent-modules</artifactId>
<version>1.1</version>
<packaging>pom</packaging>
<modules>
<module>module-a</module>
<module>module-b</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<filesets>
<fileset>
<directory>.</directory>
<includes>
<include>**/*.ser</include>
</includes>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
注释:maven-clean-plugin是用来清除之前生成的 target 文件(.ser结尾的是cobetura生成的报告)。这里不用再添加maven-cobetura插件,cobertura需要单独下载,在Ant 脚本中引用。
Cobertura下载地址https://download.csdn.net/download/fantasticxx/10308414 。
我这里用的是cobertura-2.1.1,下载后解压到 /EclipseWorkspace_test/ cobertura-2.1.1,可以修改成其他目录,但是要注意和 build.xml 中指定的路径一致。
modules-project的build.xml文件:
<project>
<property environment="env"/>
<property name="cobertura.dir" value="/EclipseWorkspace_test/cobertura-2.1.1"/>
<path id="cobertura.classpath">
<fileset dir="${cobertura.dir}">
<include name="cobertura-2.1.1.jar"/>
<include name="lib/**/*.jar"/>
</fileset>
</path>
<taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>
<target name="instrument">
<antcall target="instrumentModule"/>
</target>
<target name="instrumentModule">
<property name="classes.dir" value="target/classes"/>
<cobertura-instrument todir="./module-a/${classes.dir}">
<fileset dir="./module-a/target/classes">
<include name="**/*.class"/>
</fileset>
</cobertura-instrument>
<cobertura-instrument todir="./module-b/${classes.dir}">
<fileset dir="./module-b/target/classes">
<include name="**/*.class"/>
</fileset>
</cobertura-instrument>
</target>
<target name="report" depends="merge">
<property name="src.dir" value="src/main/java/"/>
<cobertura-report datafile="sum.ser"
format="html"
destdir="./target/report">
<!-- Add all modules that should be included below -->
<fileset dir="./module-a/${src.dir}"/>
<fileset dir="./module-b/${src.dir}"/>
</cobertura-report>
</target>
<target name="merge">
<cobertura-merge datafile="sum.ser">
<fileset dir=".">
<include name="**/cobertura.ser"/>
</fileset>
</cobertura-merge>
</target>
</project>
module-a
module-a的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.function</groupId>
<artifactId>parent-modules</artifactId>
<version>1.1</version>
</parent>
<groupId>com.function</groupId>
<artifactId>module-add</artifactId>
<version>1.1</version>
<dependencies>
<dependency>
<groupId>com.function</groupId>
<artifactId>module-multiply</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.cobertura</groupId>
<artifactId>cobertura</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
</project>
注释:module-a的pom.xml文件需要添加 Cobertura 依赖,这样在test phase才能记录执行的踪迹。
Eclipse中会提示错误:Missing artifact com.sun:tools:jar:0
该错误可以忽略,也可以使用下面的方式解决:
1. 将\Java\jdk1.8.0_112\lib目录下的tools.jar拷贝到\.m2\repository\com\sun\tools\1.5.0目录下
2. 在module-a的pom.xml文件添加依赖
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
</dependency>
module-a的FcuntionA.java文件
package com.functiona;
public class FunctionA {
public int add (int a, int b) {
return a + b;
}
}
module-a的FcuntionTest.java文件
package com.function;
import org.junit.Test;
import com.functiona.FunctionA;
import com.functionb.FunctionB;
import junit.framework.Assert;
public class FunctionTest {
@Test
public void shouldCalculateFibonacci() {
FunctionA functionA = new FunctionA();
int actualA = functionA.add(1, 2);
Assert.assertEquals(3, actualA);
FunctionB functionB = new FunctionB();
int actualB = functionB.multiply(1, 2);
Assert.assertEquals(2, actualB);
}
}
module-b
module-b的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.function</groupId>
<artifactId>parent-modules</artifactId>
<version>1.1</version>
</parent>
<groupId>com.function</groupId>
<artifactId>module-multiply</artifactId>
<version>1.1</version>
</project>
module-b的FcuntionB.java文件
package com.functionb;
public class FunctionB {
public int multiply(int a, int b) {
return a * b;
}
}
modules-project根目录下顺序执行下面的指令
mvn clean compile
ant instrument
mvn test
ant report
可以得到报告:
modules-project\target\report 目录下的 index.xml 文件
<property environment="env"/>
<property name="cobertura.dir" value="/EclipseWorkspace_test/cobertura-2.1.1"/>
<path id="cobertura.classpath">
<fileset dir="${cobertura.dir}">
<include name="cobertura-2.1.1.jar"/>
<include name="lib/**/*.jar"/>
</fileset>
</path>
<taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>