【问题标题】:Merging Integration and Unit test reports with JaCoCo使用 JaCoCo 合并集成和单元测试报告
【发布时间】:2015-10-26 15:42:39
【问题描述】:

我正在使用带有 JaCoCo 插件的 maven 生成故障安全和万无一失的报告,但我只能设法将它们放在单独的报告中。我也想有一个整体覆盖视图(单元测试和集成测试之间的合并)。

在我认为是彻底的谷歌搜索之后,我只能找到一种使用声纳的方法。有没有更简单的方法来做到这一点?

相关问题:Maven separate Unit Test and Integration Tests

【问题讨论】:

    标签: maven code-coverage jacoco maven-surefire-plugin maven-failsafe-plugin


    【解决方案1】:

    我最近实现了这个:经过一些令人头疼的测试和大量测试,我有了一个运行良好的配置。

    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>${jacoco.version}</version>
        <executions>
            <execution>
                <id>pre-unit-test</id>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
                <configuration>
                    <destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
                    <propertyName>surefireArgLine</propertyName>
                </configuration>
            </execution>
            <execution>
                <id>pre-integration-test</id>
                <goals>
                    <goal>prepare-agent-integration</goal>
                </goals>
                <configuration>
                    <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
                    <propertyName>testArgLine</propertyName>
                </configuration>
            </execution>
            <execution>
                <id>post-integration-test</id>
                <phase>post-integration-test</phase>
                <goals>
                    <goal>report</goal>
                </goals>
                <configuration>
                    <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
                    <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
                </configuration>
            </execution>
            <execution>
                <id>post-unit-test</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>report</goal>
                </goals>
                <configuration>
                    <dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
                    <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
                </configuration>
            </execution>
            <execution>
                <id>merge-results</id>
                <phase>verify</phase>
                <goals>
                    <goal>merge</goal>
                </goals>
                <configuration>
                    <fileSets>
                        <fileSet>
                            <directory>${project.build.directory}/coverage-reports</directory>
                            <includes>
                                <include>*.exec</include>
                            </includes>
                        </fileSet>
                    </fileSets>
                    <destFile>${project.build.directory}/coverage-reports/aggregate.exec</destFile>
                </configuration>
            </execution>
            <execution>
                <id>post-merge-report</id>
                <phase>verify</phase>
                <goals>
                    <goal>report</goal>
                </goals>
                <configuration>
                    <dataFile>${project.build.directory}/coverage-reports/aggregate.exec</dataFile>
                    <outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
            <argLine>${surefireArgLine}</argLine>
            <skipTests>${skip.unit.tests}</skipTests>
            <includes>
                <include>**/*UT.java</include>
                <include>**/*MT.java</include>
                <include>**/*Test.java</include>
            </includes>
            <skipTests>${skipUTMTs}</skipTests>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.12.4</version>
        <configuration>
            <skipTests>${skipTests}</skipTests>
            <skipITs>${skipITs}</skipITs>
            <argLine>${testArgLine}</argLine>
            <excludes>
                <exclude>**/*UT*.java</exclude>
            </excludes>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>integration-test</goal>
                    <goal>verify</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    如您所见,有 6 个不同的 Jacoco 执行来运行测试、合并文件并创建汇总报告。在 Jacoco 配置之上,您还需要配置 Surefire 和 Failsafe 以从 Jacoco 获取参数(Surefire 运行单元测试,而 Failsafe 运行集成测试)。

    我使用的所有配置都应该在那里,您使用它所做的是您的设计架构,以使其符合您的期望要求。就我个人而言,如果您遇到文件未被读取的问题,我建议您查看一下我排除和包含在安全和故障保护中的内容。

    【讨论】:

    • 我建议不要更改 maven-surefire-plugin 和 maven-failsafe-plugin 的默认命名约定,因为没有必要。保持约定...我强烈建议对 maven-surefire 和 maven-failsafe 使用相同的版本以及最新版本...
    • 可能是值得推荐的。我只是想给用户一个有效的代码示例,而不是“嘿,去看看这个”。
    • @BobVanDeHey 非常感谢这个 sn-p。设置 JaCoCo 配置对我来说非常有用。
    • 总是乐于帮助社区!如果您需要更多说明,请告诉我。
    • @ChadVanDeHey 在您的surefire 配置中,skipTests 似乎设置了两次。
    【解决方案2】:

    不是您要寻找的答案,但仍然...

    在大多数情况下,您不应合并单元测试和集成测试的覆盖率。

    单元测试的价值在于它们改进了应用程序的设计并确保代码的极端情况正常工作。您应该尝试让单元测试的分支覆盖率较高。

    集成测试的价值在于它们确保应用程序的主要用例正常工作,并且整个堆栈都正确集成。您应该尝试为您的集成测试提供较高的功能覆盖率。 (但使用工具来衡量功能覆盖率相当困难)。

    如果您需要集成测试来提高分支覆盖率,这强烈表明您应该审查代码设计。如果您在没有集成测试的情况下已经拥有很高的分支覆盖率,那么添加它们不应显着修改您的指标。

    请随意对这个答案投反对票,因为它有点话题并且相当固执...

    【讨论】:

      【解决方案3】:

      您应该查看包含merge 目标的 JaCoCo Maven 插件的文档。

      【讨论】:

      • 好答案!随意在下面查看我的代码示例。
      【解决方案4】:

      也许更好的实现方法是使用相同的 jacoco 文件,但让它进行另一个测试,这对我们有用 - 单元和它测试。

                  <plugin>
                      <groupId>org.jacoco</groupId>
                      <artifactId>jacoco-maven-plugin</artifactId>
                      <version>0.8.1</version>
                      <executions>
                          <execution>
                              <id>default-prepare-agent</id>
                              <goals>
                                  <goal>prepare-agent</goal>
                              </goals>
                              <configuration>
                                  <skip>${maven.surefire.skipTests}</skip>
                                  <propertyName>maven.surefire.argLine</propertyName>
                                  <!-- using the same dest file for both UT and IT -->
                                  <destFile>${sonar.jacoco.reportPath}</destFile>
                              </configuration>
                          </execution>
                          <execution>
                              <id>default-prepare-agent-integration</id>
                              <goals>
                                  <goal>prepare-agent-integration</goal>
                              </goals>
                              <configuration>
                                  <skip>${maven.failsafe.skipTests}</skip>
                                  <propertyName>maven.failsafe.argLine</propertyName>
                                  <!-- append to the UT dest file -->
                                  <destFile>${sonar.jacoco.reportPath}</destFile>
                                  <append>true</append>
                              </configuration>
                          </execution>
                      </executions>
                  </plugin>
                  <plugin>
                  <artifactId>maven-surefire-plugin</artifactId>
                  <configuration>
                      <skipTests>${maven.surefire.skipTests}</skipTests>
                      <failIfNoTests>${maven.surefire.failIfNoTests}</failIfNoTests>
                      <!-- allow argLine to be modified by other plugins, e.g. jacoco -->
                      <argLine>@{maven.surefire.argLine}</argLine>
                  </configuration>
              </plugin>
              <plugin>
                  <artifactId>maven-failsafe-plugin</artifactId>
                  <configuration>
                      <skipTests>${maven.failsafe.skipTests}</skipTests>
                      <failIfNoTests>${maven.failsafe.failIfNoTests}</failIfNoTests>
                      <!-- allow argLine to be modified by other plugins, e.g. jacoco -->
                      <argLine>@{maven.failsafe.argLine}</argLine>
                  </configuration>
              </plugin>
      

      【讨论】:

        【解决方案5】:

        在乍得的答案之上,这是我的配置。它被配置为一个名为jacoco 的单独配置文件,因此我可以轻松地打开和关闭它。它仅使用默认配置。它可以为单元测试创​​建单独的代码覆盖率报告,为集成测试创建单独的代码覆盖率报告以及组合代码覆盖率报告。

            <profile>
                <id>jacoco</id>
                <build>
                    <plugins>
                        <plugin>
                            <groupId>org.jacoco</groupId>
                            <artifactId>jacoco-maven-plugin</artifactId>
                            <executions>
                                <execution>
                                    <id>pre-unit-test</id>
                                    <goals>
                                        <goal>prepare-agent</goal>
                                    </goals>
                                </execution>
                                <execution>
                                    <id>post-unit-test</id>
                                    <phase>test</phase>
                                    <goals>
                                        <goal>report</goal>
                                    </goals>
                                </execution>
                                <execution>
                                    <id>pre-integration-test</id>
                                    <goals>
                                        <goal>prepare-agent-integration</goal>
                                    </goals>
                                </execution>
                                <execution>
                                    <id>post-integration-test</id>
                                    <goals>
                                        <goal>report-integration</goal>
                                    </goals>
                                </execution>
                                <execution>
                                    <id>merge-results</id>
                                    <phase>verify</phase>
                                    <goals>
                                        <goal>merge</goal>
                                    </goals>
                                    <configuration>
                                        <fileSets>
                                            <fileSet>
                                                <directory>${project.build.directory}</directory>
                                                <includes>
                                                    <include>*.exec</include>
                                                </includes>
                                                <excludes>
                                                    <exclude>aggregate.exec</exclude>
                                                </excludes>
                                            </fileSet>
                                        </fileSets>
                                        <destFile>${project.build.directory}/aggregate.exec</destFile>
                                    </configuration>
                                </execution>
                                <execution>
                                    <id>post-merge-report</id>
                                    <phase>verify</phase>
                                    <goals>
                                        <goal>report</goal>
                                    </goals>
                                    <configuration>
                                        <dataFile>${project.build.directory}/aggregate.exec</dataFile>
                                        <outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>
                                    </configuration>
                                </execution>
                            </executions>
                        </plugin>
                    </plugins>
                </build>
            </profile>
        

        【讨论】:

          【解决方案6】:

          我明白单元测试应该真正成为代码覆盖的来源......但有时,人们希望有能力知道对吗?这是我所做的(这是来自使用 gradle)。

          plugins {
              [...]
              id 'jacoco'
          }
          
          [...]
          
          test {
              jacoco { /* specify the "exec" data file name (see the "Unit" in there) */
                  destinationFile = file("$buildDir/jacoco/jacocoTestUnit.exec")
                  classDumpDir = file("$buildDir/jacoco/classpathdumpsUnit")
              }
              useJUnitPlatform { /* I use the JUnit Jupiter @Tag Annotation to create my suites... you are free to do something else */
                  excludeTags 'IT'
              }
              description = "Run unit tests"
              group = "verification"
          }
          
          task intTest(type: Test) {
              jacoco {
                  destinationFile = file("$buildDir/jacoco/jacocoTestInt.exec")
                  classDumpDir = file("$buildDir/jacoco/classpathdumpsInt")
              }
              useJUnitPlatform {
                  includeTags 'IT'
              }
              description = "Run integration tests"
              group = "verification"
          }
          
          jacocoTestReport {
              /*
               * find all test exec files and feed them to jacoco
               */
              def list = []
              def dir = new File("${buildDir}/jacoco/")
              if(dir.exists()) {
                  dir.eachFileRecurse(FileType.FILES) { file ->
                      /* gather all the "exec" files available */
                      if (file.getName().startsWith("jacocoTest") && file.getName().endsWith(".exec")) {
                          list << file.getAbsolutePath()
                      }
                  }
                  /* provide all the "exec" files to jacoco */
                  executionData.from = files(list)
              }
          
              /* 
               * you must run all tests before running jacoco.
               * We want the liberty to run partial tests instead of all,
               * so this task doesn't depend on any test task.
               */
              reports {
                  xml.enabled true
              }
          }
          

          这样,您就有可能通过以下方式从单元测试中获得覆盖率:

          ./gradlew clean test jacocoTestReport
          

          或者您可以通过以下方式获得集成测试的覆盖率:

          ./gradlew clean intTest jacocoTestReport
          

          或者您可以通过以下方式全面覆盖单元测试和集成测试:

          ./gradlew clean test inTest jacocoTestReport
          

          免责声明:我不是 Jacoco 或 Gradle 专家......请随时评论我可能忘记的任何内容。到目前为止,这非常适合我的需求。

          【讨论】:

          【解决方案7】:

          为了merge这里的报告,我有一个完整的工作解决方案。

          请注意,为了使merge 策略正常工作,阶段应按顺序执行(如果mvn testmvn verify -DskipUnitTests 将并行执行,则可能无法正常工作)。

          <!-- Jacoco is used to generate the reports for SonarQube -->
          <plugin>
              <groupId>org.jacoco</groupId>
              <artifactId>jacoco-maven-plugin</artifactId>
              <version>0.8.6</version>
          
              <configuration>
                  <skip>${skipTests}</skip>
              </configuration>
          
              <executions>
                  <!-- Prepares the property pointing to the JaCoCo runtime agent which
                       is passed as VM argument when Maven the Surefire plugin is executed. -->
                  <execution>
                      <id>pre-unit-test</id>
                      <goals>
                          <goal>prepare-agent</goal>
                      </goals>
                      <configuration>
                          <!-- Sets the path to the file which contains the execution data. -->
                          <destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
                          
                          <!-- Sets the name of the property containing the settings for JaCoCo runtime agent. -->
                          <propertyName>surefireArgLine</propertyName>
                      </configuration>
                  </execution>
                  
                  <!-- Make sure that after the Unit Tests execution, the jacoco-ut.exec file is generated,
                       will be merged to the aggregation file -->
                  <execution>
                      <id>post-unit-merge</id>
                      <phase>test</phase>
                      <goals>
                          <goal>merge</goal>
                      </goals>
                      <configuration>
                          <fileSets>
                              <fileSet>
                                  <directory>${project.build.directory}</directory>
                                  <includes>
                                      <include>**/coverage-reports/*.exec</include>
                                  </includes>
                              </fileSet>
                          </fileSets>
                          <destFile>${project.build.directory}/coverage-reports/jacoco_aggregation.exec</destFile>
                      </configuration>
                  </execution>
                  
                  <!-- Ensures that the code coverage report is created/updated after unit tests have been run. -->
                  <execution>
                      <id>post-unit-test</id>
                      <phase>test</phase>
                      <goals>
                          <goal>report</goal>
                      </goals>
                      <configuration>
                          <!-- Sets the path to the file which contains the execution data. -->
                          <dataFile>${project.build.directory}/coverage-reports/jacoco_aggregation.exec</dataFile>
                          
                          <!-- Sets the output directory for the code coverage report. -->
                          <outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
                      </configuration>
                  </execution>
          
                  <!-- Prepares the property pointing to the JaCoCo runtime agent which
                      is passed as VM argument when Maven the Failsafe plugin is executed. -->
                  <execution>
                      <id>pre-integration-test</id>
                      <phase>pre-integration-test</phase>
                      <goals>
                          <goal>prepare-agent</goal>
                      </goals>
                      <configuration>
                          <!-- Sets the path to the file which contains the execution data. -->
                          <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
                          
                          <!-- Sets the name of the property containing the settings for JaCoCo runtime agent. -->
                          <propertyName>failsafeArgLine</propertyName>
                      </configuration>
                  </execution>
                  
                  <!-- Make sure that after the Integration Test execution, the jacoco-it.exec file is generated,
                       will be merged to the aggregation file -->
                  <execution>
                      <id>post-integration-merge</id>
                      <phase>post-integration-test</phase>
                      <goals>
                          <goal>merge</goal>
                      </goals>
                      <configuration>
                          <fileSets>
                              <fileSet>
                                  <directory>${project.build.directory}</directory>
                                  <includes>
                                      <include>**/coverage-reports/*.exec</include>
                                  </includes>
                              </fileSet>
                          </fileSets>
                          <destFile>${project.build.directory}/coverage-reports/jacoco_aggregation.exec</destFile>
                      </configuration>
                  </execution>
                  
                  <!-- Ensures that the code coverage report is created/updated after integration tests have been run. -->
                  <execution>
                      <id>post-integration-test</id>
                      <phase>post-integration-test</phase>
                      <goals>
                          <goal>report</goal>
                      </goals>
                      <configuration>
                          <!-- Sets the path to the file which contains the execution data. -->
                          <dataFile>${project.build.directory}/coverage-reports/jacoco_aggregation.exec</dataFile>
                          
                          <!-- Sets the output directory for the code coverage report. -->
                          <outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
                      </configuration>
                  </execution>
              </executions>
          </plugin>
          
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-surefire-plugin</artifactId>
              <configuration>
                  <!-- Sets the VM argument line used when unit tests are run. -->
                  <argLine>${surefireArgLine}</argLine>
              </configuration>
          </plugin>
          
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-failsafe-plugin</artifactId>
              <configuration>
                  <!-- Sets the VM argument line used when integration tests are run. -->
                  <argLine>${failsafeArgLine}</argLine>
              </configuration>
          </plugin>
          

          现在,由于报告已生成,可以执行 sonar 命令以发布报告:

          mvn sonar:sonar -Dsonar.coverage.jacoco.xmlReportPaths="target/site/jacoco/jacoco.xml"
          

          【讨论】:

            【解决方案8】:

            这是开箱即用的。

            说明

            prepare-agent 目标默认与 SureFire 和 FailSafe 插件集成(确切地说,prepare-agent 设置的 argLine 参数由两个插件使用)。此外,prepare-agent 默认配置 Jacoco,以便在文件已存在时附加覆盖结果,因此最终您会得到单个 target/jacoco.exec 文件,其中包含单元测试和集成测试的结果,组合在一起。

            以防万一这是相关配置,因为您看到默认设置没有任何变化:):

                <plugins>
                  <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.2</version>
                    <executions>
                      <execution>
                        <goals>
                          <goal>test</goal>
                        </goals>
                      </execution>
                    </executions>
                  </plugin>
            
            
                  <plugin>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>2.22.2</version>
                    <executions>
                      <execution>
                        <goals>
                          <goal>integration-test</goal>
                          <goal>verify</goal>
                        </goals>
                      </execution>
                    </executions>
                  </plugin>
            
            
                  <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>0.8.6</version>
                    <executions>
                      <execution>
                        <goals>
                          <goal>prepare-agent</goal>
                          <goal>report</goal>
                          <goal>check</goal>
                        </goals>
                      </execution>
                    </executions>
                  </plugin>
                </plugins>
            

            【讨论】:

              猜你喜欢
              • 2019-06-26
              • 1970-01-01
              • 2018-11-21
              • 2018-11-11
              • 2017-05-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-10-15
              相关资源
              最近更新 更多