为单元和集成测试生成声纳覆盖率报告

Posted

技术标签:

【中文标题】为单元和集成测试生成声纳覆盖率报告【英文标题】:generating sonar coverage reports for unit and integration tests 【发布时间】:2016-11-18 09:55:55 【问题描述】:

我已经看了一段时间关于 *** 的不同文章和答案,但我还没有找到适合我的案例的有效解决方案。我对 jacoco、maven 和 sonar 如何共同创建报告的理解肯定有问题,所以我要寻求帮助。

我有一个多模块的maven项目,结构如下(稍微简化了一点):

root-folder/
├── module1/
│   ├── module1_1/
│   ├── module2_2/
├── module2/
│   ├── module2_1/
│   └── module2_2/
├── module3/
│   ├── module3_1/
│       ├── module3_1_1/
│   └── module3_2/
│   └── module3_3/
│   └── module3_4/
├── parent/
├── itest/
│   ├── itest_helper1/
│   └── itest_helper2/
│   └── actual_tests/
├── module4/

请允许我稍微扩展一下。父模块只是一个包含整个依赖项及其版本的 pom。这个 pom 被用作 level1 的每个其他模块的父级(直接在 root 下)。例如,模块 3_1_1 具有父模块 3_1/pom,而后者又具有父模块/pom。我还有一个我排除的功能模块,因为它用于将模块公开给其他项目,这在我的情况下没有用。

大多数模块(但不是全部)都使用 junit 框架进行单元测试。集成测试位于一个单独的模块中,该模块具有一些辅助子模块和一个具有实际 ITests 类的子模块。我的测试涵盖了我项目中所有的代码,因此他们测试了所有其他模块的代码。

我的根 pom 也有一些内部框架作为父级,它基本上是一个 osgi 容器、Web 服务并处理第 3 方依赖项。

我有声纳 5.6 版,但未能为集成测试创建报告。我也希望它们被合并,这样我就可以向下钻取并查看每个模块/类的测试覆盖率。我尝试了不同的选项和设置,我最近的尝试在我的根文件夹/pom.xml 中有以下内容。

 <!-- properties section-->
  <properties>
        <jacoco.version>0.7.2.201409121644</jacoco.version>
        <sonar.language>java</sonar.language>
        <sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
        <jacoco.outputDir>$project.build.directory</jacoco.outputDir>
        <jacoco.out.ut.file>jacoco-ut.exec</jacoco.out.ut.file>
        <sonar.jacoco.reportPath>$jacoco.outputDir/$jacoco.out.ut.file</sonar.jacoco.reportPath>
        <jacoco.out.it.file>jacoco-it.exec</jacoco.out.it.file>
        <sonar.jacoco.itReportPath>$jacoco.outputDir/$jacoco.out.it.file</sonar.jacoco.itReportPath>
    </properties>

<!-- plugins section-->
<profiles>
        <profile>
            <id>coverage</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <configuration>
                            <argLine>$jacoco.agent.ut.arg</argLine>
                            <!-- test failure ignore -->
                            <testFailureIgnore>true</testFailureIgnore>
                            <includes>
                                <include>**/*Test*</include>
                            </includes>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <configuration>
                            <argLine>-Xmx1024m -XX:MaxPermSize=256m $jacoco.agent.it.arg
                            </argLine>
                            <!-- Let's put failsafe reports with surefire to have access to tests
                                failures/success reports in sonar -->
                            <reportsDirectory>$project.build.directory/surefire-reports
                            </reportsDirectory>
                            <includes>
                                <include>**/*IT*</include>
                            </includes>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.jacoco</groupId>
                        <artifactId>jacoco-maven-plugin</artifactId>
                        <version>$jacoco.version</version>
                        <executions>
                            <!-- Prepares a variable, jacoco.agent.ut.arg, that contains the info
                                to be passed to the JVM hosting the code being tested. -->
                            <execution>
                                <id>prepare-ut-agent</id>
                                <phase>process-test-classes</phase>
                                <goals>
                                    <goal>prepare-agent</goal>
                                </goals>
                                <configuration>
                                    <destFile>$sonar.jacoco.reportPath</destFile>
                                    <propertyName>jacoco.agent.ut.arg</propertyName>
                                    <append>true</append>
                                </configuration>
                            </execution>
                            <!-- Prepares a variable, jacoco.agent.it.arg, that contains the info
                                to be passed to the JVM hosting the code being tested. -->
                            <execution>
                                <id>prepare-it-agent</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>prepare-agent</goal>
                                </goals>
                                <configuration>
                                    <destFile>$sonar.jacoco.itReportPath</destFile>
                                    <propertyName>jacoco.agent.it.arg</propertyName>
                                    <append>true</append>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <!-- Integraton tests -->
        <profile>
            <id>run-its</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>integration-test</id>
                                <phase>integration-test</phase>
                                <goals>
                                    <goal>integration-test</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>verify</id>
                                <phase>verify</phase>
                                <goals>
                                    <goal>verify</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

我使用 mvn -Pcoverage,run-its clean install sonar:sonar 运行我的项目。我的单元测试似乎没问题,覆盖率和成功率都很高。老实说,我只对集成测试感兴趣,但是单元测试很容易设置,所以我也添加了它们。对于我的集成测试报告,它实际上报告了我的 itest 模块的覆盖率,这是唯一不应该报告的模块。我希望我的测试报告我的整个项目的覆盖率。

这是声纳在我的 itest 模块上运行的 jacoco 部分:

    [WARNING] You are not using the latest JaCoCo binary format version, please     consider upgrading to latest JaCoCo version.
[INFO] Analysing  D:\Home\project\root\itest\testcase\target\jacoco-it.exec
[WARNING] You are not using the latest JaCoCo binary format version, please consider upgrading to latest JaCoCo version.
[INFO] Analysing D:\Home\project\root\itest\testcase\target\sonar\jacoco-overall.exec
[INFO] No information about coverage per test.

此外,由于我的插件配置位于根 pom 中,它会尝试分析我所有模块的报告(包括没有单元测试的模块)并在声纳运行日志中引发错误,但我认为它是不是问题。非常感谢任何帮助,如果您需要,请询问更多详细信息。谢谢。

【问题讨论】:

添加为评论。我认为我的 itest 覆盖范围仅涵盖 itest 模块的原因是因为它们可能被视为单元测试?不确定它是如何发挥作用的。 您对此有什么解决办法吗?已经在堆栈上冲浪了很多年...... @4the3eam 太老了,不记得我是如何让它工作的了。我确实相信我从以下配置文件开始(将其作为答案)并使用 -Dsonar.jacoco.itReportPath 和 -Dsonar.jacoco.reportPath 使用绝对路径指向 /target 进行编译。 【参考方案1】:

使用以下配置文件作为起点并运行 mvn sonar:sonar,其中 -Dsonar.jacoco.itReportPath 和 -Dsonar.jacoco.reportPath 指向报告路径。

     <profile>
        <id>coverage</id>
        <properties>
            <jacoco.includes>com.trmsys.*</jacoco.includes>
            <jacoco.agent.jar>$project.build.directory/org.jacoco.agent-$jacoco-maven-plugin.version-runtime.jar
            </jacoco.agent.jar>
            <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
            <sonar.jacoco.reportPath>$session.executionRootDirectory/target/jacoco.exec</sonar.jacoco.reportPath>
            <sonar.jacoco.itReportPath>$session.executionRootDirectory/target/jacoco-it.exec</sonar.jacoco.itReportPath>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>prepare-agent</id>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                            <configuration>
                                <destFile>$sonar.jacoco.reportPath</destFile>
                                <propertyName>jacoco.agent.arg</propertyName>
                                <includes>
                                    <include>$jacoco.includes</include>
                                </includes>
                                <append>true</append>
                            </configuration>
                        </execution>
                        <execution>
                            <id>prepare-agent-integration</id>
                            <goals>
                                <goal>prepare-agent-integration</goal>
                            </goals>
                            <phase>initialize</phase>
                            <configuration>
                                <destFile>$sonar.jacoco.itReportPath</destFile>
                                <propertyName>jacoco.agent.it.arg</propertyName>
                                <includes>
                                    <include>$jacoco.includes</include>
                                </includes>
                                <append>true</append>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
            <pluginManagement>
                <plugins>
                    <!-- links jacoco agent to surefire for unit tests -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-surefire-plugin</artifactId>
                        <configuration>
                            <argLine>$jacoco.agent.arg</argLine>
                        </configuration>
                    </plugin>
                    <!-- links jacoco agent to failsafe for integration tests -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <configuration>
                            <argLine>$jacoco.agent.it.arg</argLine>
                        </configuration>
                    </plugin>
                </plugins>
            </pluginManagement>
        </build>
    </profile>

【讨论】:

以上是关于为单元和集成测试生成声纳覆盖率报告的主要内容,如果未能解决你的问题,请参考以下文章

结合声纳的 Jacoco 测试覆盖率

使用 Powermock 在 Sonarqube 中配置 jacoco 以进行集成和单元测试报告

如何为基于 http 的集成测试生成覆盖率报告?

Karma +Jasmine+ require JS进行单元测试并生成测试报告代码覆盖率报告

SonarQube:更新现有分析数据

声纳的 TeamCity dotCover 报告路径