学习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文件.

通过分析日志,我们基本能猜测到:

  1. cobertura-maven-plugin绑定到了maven生命周期test上.
  2. 源码编译完成后,cobertura-maven-plugin生成了自己的一套class文件来标记源码,存放在/target/generated-classes/cobertura/目录里.
  3. 测试用例执行时,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] ------------------------------------------------------------------------

我们逐个介绍一下.

  • cobertura:check

    根据最新的源码标记(生成的class文件)校验测试用例的覆盖率,如果没有达到要求,则执行失败.

  • cobertura:check-integration-test

    这个命令和cobertura:check功能是一样的,区别是二者绑定的maven生命周期不一样.cobertura:check绑定了testcobertura:check-integration-test绑定了verify.再说的明白些,maven生命周期中有一个是test跑得单元测试,还有一个是integration-test跑的集成测试.而verify前就是integration-test.即cobertura:check-integration-testcobertura:check涵盖的测试用例更多.

  • cobertura:clean

    这个好理解,就是清理掉目录/target/cobertura/中得文件.目前发现里面就一个文件cobertura.ser.

  • cobertura:cobertura

    这个插件的关键命令.标记被编译的文件,运行单元测试,生成测试报告.

  • cobertura:cobertura-integration-test

    cobertura:cobertura做了一样的事情,区别是包含了集成测试用例.

  • cobertura:dump-datafile

    在命令行输出覆盖率数据.数据依据是生成的class文件.这个命令我没搞懂他的意义何在.在后面一个有趣的实验我们会用这个命令来更好的理解cobertura-maven-plugin.

  • cobertura:help

    不解释.

  • cobertura:instrument

    标记被编译的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] <?xml version="1.0"?>
    [INFO] <coverage line-rate="0%" branch-rate="100%" lines-covered="0" lines-valid="3" branches-covered="0" branches-valid="0" version="2.1.1" timestamp="1449841922764">
    [INFO] <package name="com.qyf404.learn.maven" line-rate="0%" branch-rate="100%" lines-covered="0" lines-valid="3" branches-covered="0" branches-valid="0" />
    [INFO] </coverage>
  • 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] <?xml version="1.0"?>
    [INFO] <coverage line-rate="100%" branch-rate="100%" lines-covered="3" lines-valid="3" branches-covered="0" branches-valid="0" version="2.1.1" timestamp="1449842157556">
    [INFO] <package name="com.qyf404.learn.maven" line-rate="100%" branch-rate="100%" lines-covered="3" lines-valid="3" branches-covered="0" branches-valid="0" />
    [INFO] </coverage>

实验做完了.一共7步,执行了mvn cobertura:cobertura命令3次.

  1. 第一次执行报错,是因为标记文件没有生成,没有找到要解析的文件.
  2. 第二次执行,打印出了日志,但是测试用例还没执行,所以测试覆盖率还是初始状态,多数为0%.
  3. 第三次执行,打印出了日志,显示了测试覆盖情况.

校验规则

一般我们执行cobertura:coberturacobertura:cobertura-integration-test就够了.但是在做持续集成时,我们可能希望能自动化去检验测试用例的覆盖情况,比如当覆盖率低于70%时打包失败.这个时候就用到cobertura:checkcobertura: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里配置goalphase来完成命令的绑定.比如在打包前做校验,可以这么配置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的跳过执行的配置主要由三种:

  1. <configuration>中配置:

    <configuration>
        <skip>true</skip>
    </configuration>
  2. <properties>中配置:

    <properties>
        <cobertura.skip>true</cobertura.skip>
    </properties>
  3. 命令中配置mvn clean cobertura:cobertura -Dcobertura.skip=true.

结语

好了,cobertura-maven-plugin就介绍这么多了,更多cobertura-maven-plugin的使用方法大家可以参阅官方文档

本文的示例代码这里可以下到 https://github.com/qyf404/learn-maven/tree/cobertura-maven-plugin.

参考

posted on 2017-06-08 16:12  沐雨橙风丶  阅读(2691)  评论(0编辑  收藏  举报