学习Maven之Cobertura Maven Plugin
cobertura-maven-plugin是个什么鬼?
cobertura-maven-plugin
是一个校验单元测试用例覆盖率的工具,可以生成一个测试覆盖率报告,可以给单元测试用例编写提供参考.
helloword
cobertura-maven-plugin
的使用也很简单,首先你要有源码,然后要有对这个源码编写的测试代码,最后在pom.xml
中配置上cobertura-maven-plugin
执行一行命令就可以了.
我们先来准备一个源码和测试用例:
要被测试的代码
package com.qyf404.learn.maven;
public class App {
public int add(int a, int b) {
return a + b;
}
public int subtract(int a, int b) {
return a - b;
}
}
测试用例代码
package com.qyf404.learn.maven;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
public class AppTest {
private App app;
@Before
public void setUp() {
app = new App();
}
@Test
public void testAdd() throws InterruptedException {
int a = 1;
int b = 2;
int result = app.add(a, b);
Assert.assertEquals(a + b, result);
}
@Test()
public void testSubtract() throws InterruptedException {
int a = 1;
int b = 2;
int result = app.subtract(a, b);
Assert.assertEquals(a - b, result);
}
@After
public void tearDown() throws Exception {
}
}
pom.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qyf404</groupId>
<artifactId>learn-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
数据都准备好了,我们执行以下maven命令mvn cobertura:cobertura
,执行完后会在target
目录里找到site
目录,用浏览器打开里面的index.html
,这就是测试用例执行完后cobertura-maven-plugin
得出的覆盖率报告.
报告内容如下:
分析后台日志
我们再看看这时后台日志打印的内容
qyfmac$ mvn clean cobertura:cobertura
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building learn-maven 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ learn-maven ---
[INFO] Deleting /Users/qyfmac/git/learn-maven/target
[INFO]
[INFO] >>> cobertura-maven-plugin:2.7:cobertura (default-cli) > [cobertura]test @ learn-maven >>>
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ learn-maven ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/qyfmac/git/learn-maven/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ learn-maven ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/qyfmac/git/learn-maven/target/classes
[INFO]
[INFO] --- cobertura-maven-plugin:2.7:instrument (default-cli) @ learn-maven ---
[INFO] Cobertura 2.1.1 - GNU GPL License (NO WARRANTY) - See COPYRIGHT file
[INFO] Cobertura: Saved information on 1 classes.
[INFO] Cobertura: Saved information on 1 classes.
[INFO] Instrumentation was successful.
[INFO] NOT adding cobertura ser file to attached artifacts list.
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ learn-maven ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/qyfmac/git/learn-maven/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ learn-maven ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/qyfmac/git/learn-maven/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ learn-maven ---
[INFO] Surefire report directory: /Users/qyfmac/git/learn-maven/target/surefire-reports
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.qyf404.learn.maven.AppTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.335 sec
[INFO] Cobertura: Loaded information on 1 classes.
[INFO] Cobertura: Saved information on 1 classes.
Results :
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] <<< cobertura-maven-plugin:2.7:cobertura (default-cli) < [cobertura]test @ learn-maven <<<
[INFO]
[INFO] --- cobertura-maven-plugin:2.7:cobertura (default-cli) @ learn-maven ---
[INFO] Cobertura 2.1.1 - GNU GPL License (NO WARRANTY) - See COPYRIGHT file
[INFO] Cobertura: Loaded information on 1 classes.
Report time: 159ms
[INFO] Cobertura Report generation was successful.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.624 s
[INFO] Finished at: 2015-12-08T16:42:47+08:00
[INFO] Final Memory: 22M/227M
[INFO] ------------------------------------------------------------------------
-
这行日志
[INFO] >>> cobertura-maven-plugin:2.7:cobertura (default-cli) > [cobertura]test @ learn-maven >>>
告诉我们cobertura-maven-plugin
绑定到了maven生命周期test
上. -
这行日志
[INFO] --- cobertura-maven-plugin:2.7:instrument (default-cli) @ learn-maven ---
告诉我们在完成项目源码编译后,执行了cobertura:instrument
,对项目源码做了标记. -
这两行日志
[INFO] Cobertura: Loaded information on 1 classes.
[INFO] Cobertura: Saved information on 1 classes.
```
在执行测试用例时打出的,很明显`cobertura-maven-plugin`在执行测试用例时做了些事情(这只是个猜测,具体干了啥是要看源码的).
- 这行日志
[INFO] Cobertura Report generation was successful.
告诉我们生成覆盖率报告成功.而之前执行了测试用例,而且生成报告用了之前生成的class文件.
通过分析日志,我们基本能猜测到:
cobertura-maven-plugin
绑定到了maven生命周期test
上.- 源码编译完成后,
cobertura-maven-plugin
生成了自己的一套class文件来标记源码,存放在/target/generated-classes/cobertura/
目录里. - 测试用例执行时,
cobertura-maven-plugin
修改了自己生成的那套标记源码的class文件,并根据这套class文件生成了最终的覆盖率报告.
goals介绍
总体来说cobertura-maven-plugin
的使用还是很简单的.下面我们来看看cobertura-maven-plugin
里除了cobertura:cobertura
命令还有哪些命令.执行mvn cobertura:help
我们会得到该插件的一个帮助文档.
qyfmac$ mvn cobertura:help
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building learn-maven 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- cobertura-maven-plugin:2.7:help (default-cli) @ learn-maven ---
[INFO] Mojo's Maven plugin for Cobertura 2.7
This is the Mojo's Maven plugin for Cobertura. Cobertura is a free Java tool
that calculates the percentage of code accessed by tests. It can be used to
identify which parts of your Java program are lacking test coverage.
This plugin has 8 goals:
cobertura:check
Check the coverage percentages for unit tests from the last instrumentation,
and optionally fail the build if the targets are not met. To fail the build
you need to set configuration/check/haltOnFailure=true in the plugin's
configuration.
cobertura:check-integration-test
Check the coverage percentages for unit tests and integration tests from the
last instrumentation, and optionally fail the build if the targets are not
met. To fail the build you need to set configuration/check/haltOnFailure=true
in the plugin's configuration.
cobertura:clean
Clean up the files that Cobertura Maven Plugin has created during
instrumentation.
cobertura:cobertura
Instrument the compiled classes, run the unit tests and generate a Cobertura
report.
cobertura:cobertura-integration-test
Instrument the compiled classes, run the unit tests and integration tests and
generate a Cobertura report.
cobertura:dump-datafile
Output the contents of Cobertura's data file to the command line.
cobertura:help
Display help information on cobertura-maven-plugin.
Call mvn cobertura:help -Ddetail=true -Dgoal=<goal-name> to display parameter
details.
cobertura:instrument
Instrument the compiled classes.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.822 s
[INFO] Finished at: 2015-12-03T16:23:59+08:00
[INFO] Final Memory: 8M/156M
[INFO] ------------------------------------------------------------------------
我们逐个介绍一下.
-
根据最新的源码标记(生成的class文件)校验测试用例的覆盖率,如果没有达到要求,则执行失败.
-
cobertura:check-integration-test
这个命令和
cobertura:check
功能是一样的,区别是二者绑定的maven生命周期不一样.cobertura:check
绑定了test
,cobertura:check-integration-test
绑定了verify
.再说的明白些,maven生命周期中有一个是test
跑得单元测试,还有一个是integration-test
跑的集成测试.而verify
前就是integration-test
.即cobertura:check-integration-test
比cobertura:check
涵盖的测试用例更多. -
这个好理解,就是清理掉目录
/target/cobertura/
中得文件.目前发现里面就一个文件cobertura.ser
. -
这个插件的关键命令.标记被编译的文件,运行单元测试,生成测试报告.
-
cobertura:cobertura-integration-test
和
cobertura:cobertura
做了一样的事情,区别是包含了集成测试用例. -
在命令行输出覆盖率数据.数据依据是生成的class文件.这个命令我没搞懂他的意义何在.在后面
一个有趣的实验
我们会用这个命令来更好的理解cobertura-maven-plugin
. -
不解释.
-
标记被编译的class文件.执行这个命令会在目录
/target/generated-classes/cobertura
下生成一套class文件.
一个有趣的实验
为了更好的理解cobertura-maven-plugin
命令,我们现在做个有趣的实验,观察target目录和控制台下发生了什么.
-
1.我们执行命令
mvn clean
先清理掉target
中的文件. -
2.执行命令
mvn compile
编译源文件. -
3.执行
mvn cobertura:dump-datafile
命令,后台日志显示执行失败.
[ERROR] Failed to execute goal org.codehaus.mojo:cobertura-maven-plugin:2.7:dump-datafile (default-cli) on project learn-maven: Unable to dump nonexistent dataFile [/Users/qyfmac/git/learn-maven/target/cobertura/cobertura.ser] -> [Help 1]
```
-
4.执行命令
mvn cobertura:instrument
标记被编译的文件.我们会发现多了几个文件在target
目录里. -
5.执行命令
mvn cobertura:dump-datafile
打印出覆盖率信息.[INFO] --- cobertura-maven-plugin:2.7:dump-datafile (default-cli) @ learn-maven ---
[INFO] Cobertura: Loaded information on 1 classes.
[INFO]
[INFO]
[INFO]
[INFO]
```
-
6.执行命令
mvn cobertura:cobertura
生成覆盖率报告. -
7.再次执行
mvn cobertura:dump-datafile
打印出覆盖率信息.[INFO] --- cobertura-maven-plugin:2.7:dump-datafile (default-cli) @ learn-maven ---
[INFO] Cobertura: Loaded information on 1 classes.
[INFO]
[INFO]
[INFO]
[INFO]
```
实验做完了.一共7步,执行了mvn cobertura:cobertura
命令3次.
- 第一次执行报错,是因为标记文件没有生成,没有找到要解析的文件.
- 第二次执行,打印出了日志,但是测试用例还没执行,所以测试覆盖率还是初始状态,多数为0%.
- 第三次执行,打印出了日志,显示了测试覆盖情况.
校验规则
一般我们执行cobertura:cobertura
或cobertura:cobertura-integration-test
就够了.但是在做持续集成时,我们可能希望能自动化去检验测试用例的覆盖情况,比如当覆盖率低于70%时打包失败.这个时候就用到cobertura:check
和cobertura:check-integration-test
命令了.
cobertura-maven-plugin
允许用户配置一些规则,来校验测试覆盖率.
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<check>
<!--每个类的分支覆盖率-->
<branchRate>85</branchRate>
<!--每个类的代码行覆盖率-->
<lineRate>85</lineRate>
<!--校验失败则中止.即为true时如果校验失败则打包执行失败,反之则只是打出告警日志-->
<haltOnFailure>true</haltOnFailure>
<!--整体的分支覆盖率-->
<totalBranchRate>85</totalBranchRate>
<!--整体的代码行覆盖率-->
<totalLineRate>85</totalLineRate>
<!--每个包的分支行覆盖率-->
<packageBranchRate>85</packageBranchRate>
<!--每个包的代码行覆盖率-->
<packageLineRate>85</packageLineRate>
<regexes>
<!--通过表达式设定覆盖率伐值-->
<regex>
<pattern>com.qyf404.learn.*</pattern>
<branchRate>90</branchRate>
<lineRate>80</lineRate>
</regex>
</regexes>
</check>
</configuration>
</plugin>
</plugins>
</build>
</project>
默认这个校验是需要单独敲命令的,当然可以根据实际需要,在execution
里配置goal
和phase
来完成命令的绑定.比如在打包前做校验,可以这么配置execution
.
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<check>
...
</check>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>prepare-package</phase>
</execution>
</executions>
</plugin>
...
</plugins>
统计范围
有时候我们要做覆盖率统计时,不需要全部代码都做的,为了更准确的统计我们想知道的代码的测试用例覆盖率,我们就需要加一些配置,来控制统计范围.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<instrumentation>
<!-- 这种方式我没试验成功.如果有谁配置生效了,请留言告知 http://qyf404.cnblogs.com
<ignores>
<ignore>com.example.boringcode.*</ignore>
</ignores>
-->
<!--忽略列表.根据class文件路径进行匹配-->
<excludes>
<exclude>com/qyf404/learn/**/App.class</exclude>
</excludes>
</instrumentation>
</configuration>
</plugin>
报表格式
默认情况下,插件会在target/site
下生成html格式的报表.html格式的给人看比较直观,但是如果报表要导入到其他系统还是xml解析起来简单.让我们看看怎么配置吧.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<!--这个标签一般不在这配置,一般跟着命令后面作为参数使用-->
<!--<format>xml</format>-->
<formats>
<format>xml</format>
<format>html</format>
</formats>
</configuration>
</plugin>
其实还是简单的.就是这有两个同级标签<format>
和<formats>
让人犯晕.其实也不难,<formats>
的配置允许同时输出多个格式的报表. <format>
的作用更多的时作为命令参数传入,比如mvn clean cobertura:cobertura -Dcobertura.report.format=xml
,从这我们也就知道了<format>
要比<formats>
优先级高.
跳过执行
cobertura-maven-plugin
的跳过执行的配置主要由三种:
-
<configuration>
中配置:<configuration> <skip>true</skip> </configuration>
-
<properties>
中配置:<properties> <cobertura.skip>true</cobertura.skip> </properties>
-
命令中配置
mvn clean cobertura:cobertura -Dcobertura.skip=true
.
结语
好了,cobertura-maven-plugin
就介绍这么多了,更多cobertura-maven-plugin
的使用方法大家可以参阅官方文档
本文的示例代码这里可以下到 https://github.com/qyf404/learn-maven/tree/cobertura-maven-plugin.