Maven 构建中的代码覆盖率 - 由于缺少 类 目录而跳过 JaCoCo 执行
Code coverage in maven build - Skipping JaCoCo execution due to missing classes directory
如果我只有一个项目,但现在我有一个多模块项目,我能够使代码覆盖率正常工作。
我的应用程序是在 api
项目中构建的,我所有的集成测试都是 运行 在一个单独的项目中,该项目使用作为先前模块构建的工件。
构建运行但我没有收到代码覆盖率报告,而是收到信息消息:
Skipping JaCoCo execution due to missing classes directory
我的覆盖率报告文件 jacoco-it.exec
已创建,但似乎 jacoco
插件需要项目中的 类 测试在 运行 中。
有人能告诉我当 类 在另一个模块中时我需要做什么才能创建覆盖率报告吗?
经过反复试验,我设法找到了某种变通方法。
似乎 jacoco 插件很乐意在没有 类 的情况下创建 exec 文件,但没有它们它不会创建报告,我不明白 jacoco 是如何在内部工作的所以如果有人知道你能解释一下吗是吗?
我也不确定我所做的是否可靠,但它似乎确实报告了我的 selenium 驱动测试的覆盖率。
我自己想出的(可能的)解决方案是使用 maven 资源插件复制 类,它已从我的 target\cargo 中的 war 文件中展开..目录进入目录target\classes:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>pre-integration-test</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target/cargo/configurations/tomcat7x/webapps/calculator-api/WEB-INF/classes</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*Config*.*</exclude>
<exclude>**/*Initialiser*.*</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
这似乎让 jacoco 插件很开心,我得到了我的代码覆盖率,尽管插件现在似乎忽略了我的排除列表。
有谁知道这是否真的是一个解决方案,它 'seems' 可以工作,但我无法在网上找到任何推荐的方法,我也不确定为什么 jacoco 代理设置上的排除选项up 似乎不再有效。
我已经设法绕过 jacoco 插件不排除文件,只是不使用资源插件复制它们,但我仍然不明白 jacoco 是如何工作的。
您可以使用目标 jacoco:report-aggregate
,它专门用于在单独的测试模块中创建覆盖率报告。
这是一个例子:
project
└─ module ⇦ module with sources
└─ module-test ⇦ module with tests
那么你所要做的就是在 "module-test" 的 pom.xml 中使用这个目标 :
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>jacoco-report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
还要注意您在依赖项中使用的范围,如 docs 中所述。
尽管 jacoco:report-aggregate
用于聚合报告依赖关系,但它在我的情况下不起作用 - 我使用的项目结构如下:
project
└─ module-api ⇦ API definition
└─ module-spec ⇦ module with black box tests through the API
└─ module-impl1 ⇦ implementation 1 of the API
└─ module-impl2 ⇦ another implementation of the API
└─ module-test1 ⇦ some dependencies + impl1, apply the tests from spec
└─ module-test2 ⇦ some dependencies + impl2, apply the tests from spec
在这种情况下,report-aggregate
生成了一个空报告。 module-test1 和 module-test2 项目是POM封装类型,也不适合运行 report
,因为需要在target/classes目录下类 .
我的解决方案
我将 jacoco 插件配置为 转储 类 it instruments 在项目的 target/classes 目录中添加:
<classDumpDir>${project.build.outputDirectory}</classDumpDir>
这使得常规 report
目标得以实现。完整代码为:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<configuration>
<destFile>${project.build.directory}/coverage-reports/code-coverage.exec</destFile>
<dataFile>${project.build.directory}/coverage-reports/code-coverage.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/code-coverage</outputDirectory>
<propertyName>jacocoArgLine</propertyName>
<classDumpDir>${project.build.outputDirectory}</classDumpDir>
</configuration>
<executions>
<execution>
<id>prepare-jacoco-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
请注意,已检测的 类 来自所有依赖项,因此需要进行一些过滤以缩小报告范围。参见:https://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html
我有类似的项目结构——主要代码在一个模块中,测试在另一个模块中——并且在 jacoco 报告中遇到了类似的问题。
我的解决方案1:
通过maven-resources-plugin
将/classes
文件夹复制到测试模块。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-classes-to-test-module</id>
<goals>
<goal>testResources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${project.basedir}/../main-module/target/classes</directory>
</resource>
</resources>
<outputDirectory>
${project.build.outputDirectory}
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
但是如果你的代码中包含了lambdas, anonymous 类之类的,那么结果报告可能覆盖不了一些类,因为类会因为不同prepare-agent
运行。
我的方案二:
使用 report-aggregate
目标。
在父 POM 中,我有这样的配置:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
测试模块的 POM 包含这些行:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
请记住,依赖范围对于 report-aggregate
目标 (jacoco docs) 很重要。如果您的测试模块只有测试范围的依赖项,您将得到一个空报告。因此,您应该将范围设置为编译、运行时或为您希望在报告中看到的那些工件提供。例如:
<dependency>
<groupId>my.project</groupId>
<artifactId>main-module-classes</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
如果我只有一个项目,但现在我有一个多模块项目,我能够使代码覆盖率正常工作。
我的应用程序是在 api
项目中构建的,我所有的集成测试都是 运行 在一个单独的项目中,该项目使用作为先前模块构建的工件。
构建运行但我没有收到代码覆盖率报告,而是收到信息消息:
Skipping JaCoCo execution due to missing classes directory
我的覆盖率报告文件 jacoco-it.exec
已创建,但似乎 jacoco
插件需要项目中的 类 测试在 运行 中。
有人能告诉我当 类 在另一个模块中时我需要做什么才能创建覆盖率报告吗?
经过反复试验,我设法找到了某种变通方法。
似乎 jacoco 插件很乐意在没有 类 的情况下创建 exec 文件,但没有它们它不会创建报告,我不明白 jacoco 是如何在内部工作的所以如果有人知道你能解释一下吗是吗?
我也不确定我所做的是否可靠,但它似乎确实报告了我的 selenium 驱动测试的覆盖率。
我自己想出的(可能的)解决方案是使用 maven 资源插件复制 类,它已从我的 target\cargo 中的 war 文件中展开..目录进入目录target\classes:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>pre-integration-test</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target/cargo/configurations/tomcat7x/webapps/calculator-api/WEB-INF/classes</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*Config*.*</exclude>
<exclude>**/*Initialiser*.*</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
这似乎让 jacoco 插件很开心,我得到了我的代码覆盖率,尽管插件现在似乎忽略了我的排除列表。
有谁知道这是否真的是一个解决方案,它 'seems' 可以工作,但我无法在网上找到任何推荐的方法,我也不确定为什么 jacoco 代理设置上的排除选项up 似乎不再有效。
我已经设法绕过 jacoco 插件不排除文件,只是不使用资源插件复制它们,但我仍然不明白 jacoco 是如何工作的。
您可以使用目标 jacoco:report-aggregate
,它专门用于在单独的测试模块中创建覆盖率报告。
这是一个例子:
project
└─ module ⇦ module with sources
└─ module-test ⇦ module with tests
那么你所要做的就是在 "module-test" 的 pom.xml 中使用这个目标 :
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>jacoco-report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
还要注意您在依赖项中使用的范围,如 docs 中所述。
尽管 jacoco:report-aggregate
用于聚合报告依赖关系,但它在我的情况下不起作用 - 我使用的项目结构如下:
project
└─ module-api ⇦ API definition
└─ module-spec ⇦ module with black box tests through the API
└─ module-impl1 ⇦ implementation 1 of the API
└─ module-impl2 ⇦ another implementation of the API
└─ module-test1 ⇦ some dependencies + impl1, apply the tests from spec
└─ module-test2 ⇦ some dependencies + impl2, apply the tests from spec
在这种情况下,report-aggregate
生成了一个空报告。 module-test1 和 module-test2 项目是POM封装类型,也不适合运行 report
,因为需要在target/classes目录下类 .
我的解决方案
我将 jacoco 插件配置为 转储 类 it instruments 在项目的 target/classes 目录中添加:
<classDumpDir>${project.build.outputDirectory}</classDumpDir>
这使得常规 report
目标得以实现。完整代码为:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<configuration>
<destFile>${project.build.directory}/coverage-reports/code-coverage.exec</destFile>
<dataFile>${project.build.directory}/coverage-reports/code-coverage.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/code-coverage</outputDirectory>
<propertyName>jacocoArgLine</propertyName>
<classDumpDir>${project.build.outputDirectory}</classDumpDir>
</configuration>
<executions>
<execution>
<id>prepare-jacoco-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
请注意,已检测的 类 来自所有依赖项,因此需要进行一些过滤以缩小报告范围。参见:https://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html
我有类似的项目结构——主要代码在一个模块中,测试在另一个模块中——并且在 jacoco 报告中遇到了类似的问题。
我的解决方案1:
通过maven-resources-plugin
将/classes
文件夹复制到测试模块。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-classes-to-test-module</id>
<goals>
<goal>testResources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${project.basedir}/../main-module/target/classes</directory>
</resource>
</resources>
<outputDirectory>
${project.build.outputDirectory}
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
但是如果你的代码中包含了lambdas, anonymous 类之类的,那么结果报告可能覆盖不了一些类,因为类会因为不同prepare-agent
运行。
我的方案二:
使用 report-aggregate
目标。
在父 POM 中,我有这样的配置:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
测试模块的 POM 包含这些行:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
请记住,依赖范围对于 report-aggregate
目标 (jacoco docs) 很重要。如果您的测试模块只有测试范围的依赖项,您将得到一个空报告。因此,您应该将范围设置为编译、运行时或为您希望在报告中看到的那些工件提供。例如:
<dependency>
<groupId>my.project</groupId>
<artifactId>main-module-classes</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>