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

n3schb8v  于 2022-10-26  发布在  Maven
关注(0)|答案(8)|浏览(295)

我正在用Maven和JaCoCo插件生成故障保险和可靠的报告,但我只能设法将它们放在单独的报告中。我也希望有一个全面的覆盖率视图(合并单元测试和集成测试)。
在我认为是彻底的谷歌搜索之后,我只能找到一种方法来用声纳来做到这一点。有没有更简单的方法来做这件事?
相关问题:Maven separate Unit Test and Integration Tests

qncylg1j

qncylg1j1#

我最近实现了这一点:在经历了一些令人头疼的问题和大量测试之后,我有了一个工作得很好的配置。

<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运行集成测试)。
我使用的所有配置都应该在那里,您使用它所做的是您的设计架构,以使其符合您所需的要求。就我个人而言,如果您遇到文件未被读取的问题,我建议您查看一下我在surefire和FailSafe中排除和包含的内容。

d6kp6zgx

d6kp6zgx2#

不是你想要的答案,但还是...
在大多数情况下,您不应该合并单元测试和集成测试的覆盖率。
单元测试的价值在于它们改进了应用程序的设计,并确保代码的边框正确工作。您应该尝试对您的单元测试进行高分支复盖率。
集成测试的价值在于,它们可以确保应用程序的主要用例正常工作,并确保整个堆栈正确集成。您应该尝试为您的集成测试提供高的功能覆盖率。(但用工具来衡量功能覆盖率是相当困难的)。
如果您需要集成测试来提高分支覆盖率,这是一个强烈的迹象,表明您应该检查代码的设计。如果您已经在没有集成测试的情况下拥有较高的分支机构覆盖率,则添加这些测试不会显著改变您的指标。

8yparm6h

8yparm6h3#

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

unftdfkk

unftdfkk4#

也许更好的方法是实现使用相同的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>
fjaof16o

fjaof16o5#

在乍得答案的基础上,以下是我的配置。它被配置为一个名为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>
qjp7pelc

qjp7pelc6#

我明白了单元测试应该真正位于代码覆盖率的源码……但有时,一个人希望有能力知道,对吗?以下是我所做的(这来自使用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

免责声明:我不是雅可可或GradleMaven。对我可能忘记的任何事情,请随时发表评论。到目前为止,这很好地满足了我的需求。

zvokhttg

zvokhttg7#

为了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"
4xy9mtcn

4xy9mtcn8#

这是开箱即用的。

说明

默认情况下,prepare-agent目标集成了surefire插件和故障保护插件(确切地说,由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>

相关问题