JaCoCo 与 Maven - 缺少执行数据文件

JaCoCo with Maven - missing execution data file

我们有一个 Maven 多模块项目,由一个父项 (HelloWorld) 和不同的子项 (HelloWorldServices 和 HelloWorldPresentation) 组成,并使用 Jenkins 进行构建。

运行测试成功后的错误是

[INFO] --- jacoco-maven-plugin:0.7.6.201602180812:report (default-cli) @ HelloWorldServices ---
[INFO] Skipping JaCoCo execution due to missing execution data file:/var/lib/jenkins/workspace/HelloWorld/HelloWorldServices/target/jacoco.exec

前面几行

[INFO] --- jacoco-maven-plugin:0.7.6.201602180812:prepare-agent (default-cli) @ HelloWorldServices ---
[INFO] argLine set to -javaagent:/var/lib/jenkins/.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/HelloWorld/HelloWorldServices/target/jacoco.exec

这是我定义父 pom JaCoCo 插件的方式:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.6.201602180812</version>
    <configuration>
        <destfile>${project.artifactId}/target/jacoco.exec</destfile>
        <datafile>${project.artifactId}/target/jacoco.exec</datafile>
    </configuration>

    <executions>
        <execution>
            <id>jacoco-initialize</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>jacoco-site</id>
            <phase>package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

我没有在任何 pom 中明确提到 surefire。我还尝试了您在任何地方都能找到的将 argLine 放入配置中的方法,但结果都相同。 JaCoCo .exec 文件从未创建过,无论我做什么。至于目标,我使用

mvn clean install jacoco:prepare-agent jacoco:report

因为当我省略 jacoco 目标时,它甚至不显示 INFO 消息。

您不应在安装阶段之后而是之前调用代理,因此不要调用:

mvn clean install jacoco:prepare-agent jacoco:report

你应该调用

mvn clean jacoco:prepare-agent install jacoco:report

主要原因是:代理不会参与构建生命周期,test阶段已经作为install阶段的一部分执行,那么Maven会按照命令行调用,但为时已晚。


您可能还应该将上面的插件配置更改为:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.6.201602180812</version>
    <executions>
        <execution>
            <id>jacoco-initialize</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>jacoco-site</id>
            <phase>package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

注意:我删除了配置部分,因为它实际上指向默认值。此外,XML 元素在这里区分大小写,因此您的 datafile 元素被简单地忽略了,它应该是 dataFile。同样适用于 destFile.

prepare-agent goal is already using ${project.build.directory}/jacoco.exec as default destFile value, the same applied to the dataFile value for the report 目标。此更改的主要原因是更灵活和标准的构建,不依赖 artifactId 作为项目名称(默认,但仍然不是强制性的)并使用更通用的 ${project.build.directory} 属性而不是直接指向 target.


最后注意:确保在 build/plugins 部分而不是 build/pluginManagement/plugins 部分配置 Jacoco 插件执行。 pluginManagement 部分用于版本或配置的治理和共同协调,但如果相应的插件未在 build/plugins 下声明,它将被 忽略 。 =53=] 根据 official Maven POM reference

pluginManagement: is an element that is seen along side plugins. Plugin Management contains plugin elements in much the same way, except that rather than configuring plugin information for this particular project build, it is intended to configure project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.

(注:粗体是我的)

我认为 "destfile" 和 "datafile" 是区分大小写的,所以尝试用 "destFile" 和 "dataFile" 替换它们,也许它会起作用:)

  • JaCoCo 报告是从执行数据文件中创建的。
  • 如果此文件不存在,则 JaCoCo 报告目标将跳过报告创建。
  • 因此必须创建执行数据文件。

无法创建执行数据文件的原因如下
- 测试不存在。
- 忽略所有测试。
- 缺少 Surefire 插件。
- JaCoCo 的 prepare-agent 目标未执行,这将配置所需的 argLine 设置为 surefire。
- Surefire 插件未配置 JaCoCo 的代理。

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.5</version>
    <configuration>
        <target>
            <propertyfile file="lombok.config">
                <entry key="config.stopBubbling" value="true" />
                <entry key="lombok.addLombokGeneratedAnnotation" value="true" />
            </propertyfile>
        </target>
        <excludes>
            <exclude>**/domain/**</exclude>
            <exclude>**/enumeration/**</exclude>
            <exclude>**/exception/**</exclude>
        </excludes>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <!-- attached to Maven test phase -->
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
        <!-- Add this checking -->
        <execution>
            <id>jacoco-check</id>
            <goals>
                <goal>check</goal>
            </goals>
            <configuration>
                <rules>
                    <rule>
                        <element>PACKAGE</element>
                        <limits>
                            <limit>
                                <counter>INSTRUCTION</counter>
                                <value>COVEREDRATIO</value>
                                <minimum>65%</minimum>
                            </limit>
                        </limits>
                    </rule>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

我和你分享我的回答可能是其他人为他工作

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.5</version>
<!--                <configuration>
                    <excludes>
                        <exclude>package you want exclude</exclude>
                    </excludes>
                </configuration>-->
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <!-- attached to Maven test phase -->
                    <execution>
                        <id>report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>

<!--                    <execution>
                        <id>jacoco-check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <rule>
                                    <element>PACKAGE</element>
                                    <limits>
                                        <limit>
                                            <counter>LINE</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>0.9</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>-->

                </executions>
            </plugin>

我今天刚刚处理了这个问题,发现当我在 Surefire 插件中设置 argLine 参数时会发生这种情况(我需要为 运行 JavaFx-related 测试做)即使您的 jacoco-maven-plugin 目标中有 prepare-agent,它也会取代默认值。

所以基本上,解决方案是添加原始 argLine 并使用 @{argLine} 添加额外的 arg 行,如前所述 here:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>3.0.0-M5</version>
  <configuration>
    <argLine>@{argLine} --enable-native-access ALL-UNNAMED --add-modules jdk.incubator.foreign</argLine>
  </configuration>
</plugin>

它在 post 中提到分配 jacoco agent argline 变量 ${surefire.argLine} 但我认为这些步骤不是必需的(至少在我的情况下不是)。