【问题标题】:Integration Test Coverage in SonarQube from JaCoCo Maven plug-in showing 0%JaCoCo Maven 插件的 SonarQube 中的集成测试覆盖率显示为 0%
【发布时间】:2015-04-19 19:38:57
【问题描述】:

我们有一个多模块多语言 maven java 项目,使用 jacoco 进行覆盖率分析。 模块的主要部分是带有 REST API 的后端(Java 代码),我们的 webapp 模块包含前端(AngularJS)和 java 中的集成测试。 我们的 Jacoco-IT.exec 文件包含大约 100Kb 的数据,因此我们猜测可能会收集一些用于集成测试的 Coverage 数据。尽管如此,我们在 SonarQube 中看不到任何覆盖(使用版本 5.0 和 4.5)

我们运行构建项目并运行集成测试

mvn clean install

分析数据

mvn sonar:sonar

项目配置为多语言,但我们只是分析java代码(我们曾经有一个单语言配置,但与覆盖率数据相关的结果没有差异)

我们的父 POM:

<properties>
    <hibernate.version>4.2.2.Final</hibernate.version>
    <spring.version>3.2.3.RELEASE</spring.version>
    <resteasy.version>3.0.4.Final</resteasy.version>
    <cucumber.version>1.1.3</cucumber.version>
    <selenium-java.version>2.33.0</selenium-java.version>
    <!-- Sonar -->
    <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
    <sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath>
    <jacoco.dataFile>${project.basedir}/../target/jacoco-it.exec</jacoco.dataFile>
</properties>
<build>
   <plugins>
       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <debug>true</debug>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>

            <executions>
                <execution>
                    <id>default-prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
                <execution>
                    <id>default-prepare-agent-integration</id>
                    <goals>
                        <goal>prepare-agent-integration</goal>
                    </goals>
                </execution>
                <execution>
                    <id>default-report</id>
                    <goals>
                        <goal>report</goal>
                    </goals>
                </execution>
                <execution>
                    <id>default-report-integration</id>
                    <goals>
                        <goal>report-integration</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.16</version>
        </plugin>
    </plugins>
    <pluginManagement>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.2.201409121644</version>
            </plugin>
    </pluginMangement>
</build>

我们来自 webapp 的 POM 和集成测试:

<properties>
    <sonar.sources>src/main</sonar.sources>
</properties>
<build>
    <finalName>web</finalName>
    <plugins>
        <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>8.1.7.v20120910</version>
        <configuration>...</configuration>
        <executions>...</executions>
    </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <configuration>
                <!-- The destination file for the code coverage report has to be set to the same value
                in the parent pom and in each module pom. Then JaCoCo will add up information in
                the same report, so that, it will give the cross-module code coverage. -->
                <destFile>${project.basedir}/../target/jacoco-it.exec</destFile>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.16</version>
            <executions>
                <execution>
                    <id>default</id>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

您可以在我们的父 POM 中看到,我们将 itReportPath 配置为所有模块的同一目录中。因此,当 Sonar 分析所有模块时,它总是读取相同的覆盖率数据,并且应该将它们与当前模块的二进制文件中的调试信息对齐。 在 maven (mvn sonar:sonar) 的分析阶段,我们会收到一些不确定是否有问题的消息:

对于所有 java 模块,我们得到以下几行:

    [INFO] [17:30:42.992] Sensor SurefireSensor...
    [INFO] [17:30:42.992] parsing \git\airport-core\rest\target\surefire-reports
    [INFO] [17:30:43.009] Sensor SurefireSensor done: 17 ms
    [INFO] [17:30:43.009] Sensor JaCoCoItSensor...
    [INFO] [17:30:43.010] Analysing \git\airport-core\rest\..\target\jacoco-it.exec
    [INFO] [17:30:43.018] No information about coverage per test.
    [INFO] [17:30:43.018] Sensor JaCoCoItSensor done: 9 ms
    [INFO] [17:30:43.018] Sensor JaCoCoOverallSensor...
    [INFO] [17:30:43.027] Analysing \git\airport-core\rest\target\sonar\jacoco-overall.exec
    [INFO] [17:30:43.046] No information about coverage per test.
    [INFO] [17:30:43.046] Sensor JaCoCoOverallSensor done: 28 ms

是“没有关于每次测试覆盖率的信息”。一个问题?好的,我们不知道是哪个测试导致了覆盖率,但我们应该在 SonarQube 中得到一个不同于 0% 的值

对于我们的 webapp 模块,它不包含任何 java 源/类,除了集成测试源本身,我们得到以下几行:

    [INFO] [17:30:48.370] Sensor JaCoCoItSensor...
    [INFO] [17:30:48.370] No JaCoCo analysis of project coverage can be done since there is no class files.
    [INFO] [17:30:48.370] Sensor JaCoCoItSensor done: 0 ms

这应该不是问题,因为此模块中没有类。 这个观察正确吗?

在我们的配置基于官方 SonarCube 演示配置 (https://github.com/SonarSource/sonar-examples/tree/master/projects/languages/java/code-coverage/combined%20ut-it/combined-ut-it-multimodule-maven-jacoco) 的主要部分中,我们刚刚添加了“prepare-agent-integration”目标。当然,也将其更改为多语言项目。

我们在网络上发现了很多被贬低的信息(argLine 设置等),这些信息对我们没有任何改变。

我们使用的文档和教程的链接:

【问题讨论】:

  • 你的类文件在哪里? Maven 使用的默认位置并不总是由所有插件输出目录映射。我不确定,但我猜 maven 使用“/target”,但有些插件可能使用“/bin”(或相反)。为避免这种情况,您可以设置
  • 这些类都在目标/类中,除了刚刚测试的 webapp。这些类在目标/测试类中。
  • 在声纳分析运行期间,它还会打印出二进制文件的正确路径。
  • 您可以尝试在&lt;build&gt; 标签中设置以下两项:&lt;sourceDirectory&gt;src/main&lt;/sourceDirectory&gt;&lt;outputDirectory&gt;target&lt;/outputDirectory&gt;。运行测试。如果它不起作用,请删除 &lt;properties&gt; 标签及其内容并重新运行。
  • 我现在将我的父 POM 更改为:&lt;build&gt; &lt;sourceDirectory&gt;src/main&lt;/sourceDirectory&gt; &lt;outputDirectory&gt;target&lt;/outputDirectory&gt; &lt;plugins&gt;... 但我能注意到的唯一区别是 webapp 模块(运行 IT 并且没有 java 类)的消息现在有以下消息分析(mvn sonar:sonar):Analysing target\jacoco-it.exec Coverage information was not collected. Perhaps you forget to include debug information into compiled classes? 之前:No JaCoCo analysis of project coverage can be done since there is no class files.

标签: maven configuration sonarqube integration-testing jacoco-maven-plugin


【解决方案1】:

当我为Jersey 配置 JaCoCo 时,我也有同样的经历。我最终应用了 二分法 来找出哪些模块导致整个项目的代码覆盖率下降到 0%。

如果我没记错的话,最大的惊喜是maven-shade-plugin,它以某种方式破坏了收集的覆盖率和类位置之间的关联,导致 Sonar 显示 0% 的代码覆盖率。我最终通过将其绑定到阶段none 来禁用它的执行以修复它(请参阅this commit)。

例如,这是如何扩展子模块的 pom.xml 以使声纳工作(假设声纳是使用 sonar maven 配置文件执行的)。

<profile>
    <id>sonar</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <!-- disable parallel execution so that JaCoCo listener can properly work -->
                    <parallel>none</parallel>
                    <perCoreThreadCount>false</perCoreThreadCount>
                    <forkCount>1</forkCount>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <id>shade-archive</id>
                        <phase>none</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-debug-all</artifactId>
            <optional>false</optional>
        </dependency>
    </dependencies>
</profile>

【讨论】:

    【解决方案2】:

    在与 Jacoco 和 Maven 打了很长时间之后,只有这种方式对我有用:

    1. 在 pom.xml 中创建配置文件

      <profile>
        <id>coverage-per-test</id>
        <build>
          <plugins>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.19.1</version>
              <configuration>
               <!-- disable parallel execution so that JaCoCo listener can properly work -->
                <parallel>none</parallel>
                <perCoreThreadCount>false</perCoreThreadCount>
                <forkCount>1</forkCount>
                <properties>
                  <property>
                    <name>listener</name>
                    <value>org.sonar.java.jacoco.JUnitListener</value>
                  </property>
                </properties>
              </configuration>
            </plugin>
          </plugins>
        </build>
      
        <dependencies>
          <dependency>
            <groupId>org.sonarsource.java</groupId>
            <artifactId>sonar-jacoco-listeners</artifactId>
            <version>3.10</version>
            <scope>test</scope>
          </dependency>
        </dependencies>
      </profile>
      
    2. 将maven surefire插件更新到最新版本

    3. 执行命令:

      mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install -Pcoverage-per-test -Dmaven.test.failure.ignore=true
      
      mvn sonar:sonar
      

    类似于github sonar example中的描述

    【讨论】:

      【解决方案3】:

      我正在使用类似的设置,并且一切都与以下配置完美配合:

      但是 maven-surefire-plugin 最初引起了麻烦。这就是为什么我必须在 argLine 标记中添加@{argLine},因为jacoco-maven-plugin:prepare-agent 目标在maven-surefire-plugin 之前执行。 (见https://stackoverflow.com/a/25774988

      希望我能帮上忙

      <plugins>
          <plugin>
              <groupId>org.sonarsource.scanner.maven</groupId>
              <artifactId>sonar-maven-plugin</artifactId>
              <version>3.4.0.905</version>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-surefire-plugin</artifactId>
      
              <executions>
                  <execution>
                      <phase>test</phase>
                  </execution>
              </executions>
              <configuration>
                  <!-- the @{argLine} is needed for proper jacoco execution -->
                  <argLine>@{argLine} -Xmx256m</argLine>
              </configuration>
          </plugin>
      
          <plugin>
              <groupId>org.jacoco</groupId>
              <artifactId>jacoco-maven-plugin</artifactId>
              <version>0.7.9</version>
              <executions>
                  <execution>
                      <id>jacoco-initialize</id>
                      <goals>
                          <goal>prepare-agent</goal>
                      </goals>
                  </execution>
                  <!-- generate fancy html report -->
                  <execution>
                      <id>jacoco-site</id>
                      <phase>package</phase>
                      <goals>
                          <goal>report</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
      </plugins>
      

      【讨论】:

        【解决方案4】:

        考虑到其他答案,我想添加一件事,这对于显示 Sonar 的测试覆盖率很重要:

        1. 您必须先构建项目,然后才能显示覆盖范围:mvn clean install
        2. 您必须在没有 -DskipTests 的情况下构建
        3. 您必须为运行测试的插件(surefire、failsafe、...插件)保留正确的配置 - 仅考虑 &lt;includes&gt; 或类似配置包含在插件配置中的那些测试,才会显示覆盖率。

        【讨论】:

          【解决方案5】:

          我使用 JUnit,在我的情况下,问题是因为除了 JUnit 之外,我的 pom.xml 中还有 TestNG 依赖项。移除这种不必要的依赖后,一切都开始按预期工作了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-02-12
            • 1970-01-01
            • 2022-07-01
            • 2019-12-23
            • 2017-05-31
            • 2017-12-09
            • 2014-04-09
            • 1970-01-01
            相关资源
            最近更新 更多