jacoco简单集成测试解决方案

jacoco simple integration test solution

我遵循标准的 Maven 模式,我使用单独的模块进行集成测试。这个模块有一个包装器 class 执行主要依赖的 jar 项目。

虽然jar项目有自己的测试用例,但我对执行这些不感兴趣。我想在集成测试执行时查看 jar 项目中的代码覆盖率。简单,没有报告聚合。

让我引用 http://www.jacoco.org/jacoco/trunk/doc/report-aggregate-mojo.html 即使它的名字包含一种 "aggregation":

This also allows to create coverage reports when tests are in separate projects than the code under test, for example in case of integration tests.

我们试试吧。给定 jar/src/main/java/example/Example.java:

package example;
public class Example {
  // to be covered by unit test
  public void a() {
    System.out.println("a");
  }

  // to be covered by integration test    
  public void b() {
    System.out.println("b");
  }
}

单元测试jar/src/test/java/example/ExampleTest.java:

package example;
public class ExampleTest {
  @org.junit.Test
  public void test() {
    new Example().a();
  }
}

集成测试it/src/test/java/example/ExampleITTest.java:

package example;
public class ExampleITTest {
  @org.junit.Test
  public void test() {
    new Example().b();
  }
}

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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>example</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <modules>
    <module>jar</module>
    <module>it</module>
  </modules>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.7.8</version>
        <executions>
          <execution>
            <goals>
              <goal>prepare-agent</goal>
              <goal>report</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>

jar/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>

  <parent>
    <groupId>org.example</groupId>
    <artifactId>example</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>jar</artifactId>

</project>

最后是最重要的部分 it/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>

  <parent>
    <groupId>org.example</groupId>
    <artifactId>example</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <artifactId>it</artifactId>

  <dependencies>
    <dependency>
      <groupId>org.example</groupId>
      <artifactId>jar</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <executions>
          <!--
          "report" goal can't cross boundaries of modules,
          while "report-aggregate" can, so let's use it, however
          by default it will load "jacoco.exec" from this module and from module "jar",
          so let's also change file name for this module to avoid intersection
          -->
          <execution>
            <configuration>
              <destFile>${project.build.directory}/jacoco-it.exec</destFile>
            </configuration>
          </execution>
          <execution>
            <id>it-report</id>
            <phase>verify</phase>
            <goals>
              <goal>report-aggregate</goal>
            </goals>
            <configuration>
              <dataFileIncludes>**/jacoco-it.exec</dataFileIncludes>
              <outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

在这样的设置中 mvn clean verify 将生成两个报告 - jar/target/site/jacoco 显示方法 a() 被覆盖,it/target/site/jacoco 显示方法 b() 被覆盖.

我已通过添加以下行将 Java 代理附加到应用程序服务器的 standalone.sh(启动脚本):

JAVA_OPTS="$JAVA_OPTS -javaagent:/home/jboss/.m2/repository/org/jacoco/org.jacoco.agent/0.7.6.201602180812/org.jacoco.agent-0.7.6.201602180812 -runtime.jar=destfile=/var/lib/jenkins/workspace/HDAP_JaCoCo/jacocoSoapui.exec,includes=*,append=false,output=file"

我已指定目标文件位于我的 Jenkins 作业的工作区中,该作业运行 JaCoco 代码覆盖率进行单元测试(为了获得 类 来比较我的覆盖率)。

然后我指定了两个 exec 文件的路径(一个来自单元测试,一个是我在上面提到的 Jenkins 作业的记录覆盖率报告部分中为集成测试创建的)。然后我们现在覆盖了所有测试。

注:

  • 需要停止应用程序服务器以将覆盖率转储到 exec 文件中。如果您还有其他问题,请告诉我。

  • 当您想要覆盖特定测试集时,请确保没有其他内容是 运行,因为这将使您覆盖对应用程序进行的基本上所有调用。