将集成和单元测试报告与JaCoCo合并

时间:2015-10-26 15:42:39

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

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

在我认为彻底的谷歌搜索后,我只能找到一种方法来与Sonar一起做。有没有更简单的方法呢?

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

8 个答案:

答案 0 :(得分:26)

我最近实现了这个:经过一些头痛和大量的测试后,我的配置运行得很漂亮。

{{1}}

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

我使用的所有配置都应该在那里,你用它做的是你的设计架构,使它符合你想要的要求。就个人而言,如果您遇到文件未被阅读的问题,我建议您查看我排除的内容并包含在surefire和failsafe中。

答案 1 :(得分:20)

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

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

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

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

如果您需要集成测试来改善分支机构覆盖范围,那么您就应该检查代码的设计。如果您在没有集成测试的情况下已经拥有较高的分支覆盖率,那么添加它们不应该显着修改您的指标。

随意投票给这个答案,因为这是一个主题和相当自以为是......

答案 2 :(得分:9)

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

答案 3 :(得分:1)

在Chad的答案之上,这是我的配置。它被配置为名为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>

答案 4 :(得分:1)

也许更好的方法是使用相同的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 :(得分:1)

我明白单元测试应该真正成为代码覆盖率的来源……但有时,人们希望有能力知道,对吗?这是我所做的(这是使用 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 专家...请随时评论我可能忘记的任何内容。到目前为止,这很好地满足了我的需求。

答案 6 :(得分:0)

为了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>

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

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

答案 7 :(得分:0)

这是开箱即用的。

说明

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

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

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