【问题标题】:Code coverage in maven build - Skipping JaCoCo execution due to missing classes directoryMaven 构建中的代码覆盖率 - 由于缺少类目录而跳过 JaCoCo 执行
【发布时间】:2020-06-18 16:55:23
【问题描述】:

如果我有一个项目,但现在我有一个多模块项目,我可以让代码覆盖工作正常。

我的应用程序是在 api 项目中构建的,我所有的集成测试都在一个单独的项目中运行,该项目使用作为先前模块构建的人工制品。

构建运行但我没有收到代码覆盖率报告,而是收到信息消息:

Skipping JaCoCo execution due to missing classes directory

我的覆盖率报告文件jacoco-it.exec 已创建,但似乎jacoco 插件需要运行测试的项目中的类。

谁能告诉我当类在另一个模块中时我需要做什么才能创建覆盖率报告?

【问题讨论】:

    标签: java maven code-coverage jacoco


    【解决方案1】:

    经过反复试验,我设法找到了一种解决方法。

    似乎 jacoco 插件很乐意在没有类的情况下创建 exec 文件,但它不会在没有类的情况下创建报告,我不明白 jacoco 在内部是如何工作的,所以如果有人知道,请解释一下吗?

    我也不确定我所做的是否可靠,但它似乎确实报告了我的硒驱动测试的覆盖率。

    我自己提出的(可能的)解决方案是使用 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 插件很开心,我的代码覆盖率也得到了提高,尽管现在插件似乎忽略了我的排除列表。

    有谁知道这是否真的是一个解决方案,它“似乎”有效,但我无法在网上找到任何推荐这种方法的地方,我也不确定为什么 jacoco 代理设置上的排除选项似乎不再出现上班。

    我已经设法绕过 jacoco 插件而不是通过不使用资源插件复制文件来排除文件,但我仍然不明白 jacoco 是如何工作的。

    【讨论】:

    • 我遇到了非常相似的问题,上述解决方案有效。该报告已生成,但我无法看到哪些单独的行被覆盖/未被覆盖。该类不可导航 /clickable 。仅显示统计信息。无法导航到下一级
    【解决方案2】:

    尽管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 插件配置为在项目的 target/classes 目录中转储它检测的类,方法是添加: &lt;classDumpDir&gt;${project.build.outputDirectory}&lt;/classDumpDir&gt;

    这使得常规的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

    【讨论】:

      【解决方案3】:

      我有类似的项目结构 - 主要代码在一个模块中并在另一个模块中测试 - 并且在 jacoco 报告中遇到了类似的问题。

      我的解决方案 1

      只需将/classes 文件夹复制到maven-resources-plugin 的测试模块即可。

      <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、匿名类等,那么结果报告可能不会涵盖某些类,因为由于prepare-agent 运行的不同,它会是不同的类。

      我的解决方案 2:

      使用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>
      

      【讨论】:

        【解决方案4】:

        您可以使用目标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 中提到的在依赖项中使用的范围。

        【讨论】:

          猜你喜欢
          • 2016-08-11
          • 1970-01-01
          • 2013-08-09
          • 2022-06-14
          • 2021-05-29
          • 2021-07-21
          • 2014-10-03
          相关资源
          最近更新 更多