关于配置:JaCoCo Maven插件在SonarQube中的集成测试覆盖率显示为0%

Integration Test Coverage in SonarQube from JaCoCo Maven plug-in showing 0%

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

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

1
mvn clean install

并分析数据

1
mvn sonar:sonar

该项目已配置为多语言,但是我们还只是分析了Java代码(我们以前使用的是单语言配置,但是与coverage数据相关的结果没有差异)

我们的父POM:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<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>
            maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <debug>true</debug>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            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>
            maven-surefire-plugin</artifactId>
            <version>2.16</version>
        </plugin>
    </plugins>
    <pluginManagement>
            <plugin>
                <groupId>org.jacoco</groupId>
                jacoco-maven-plugin</artifactId>
                <version>0.7.2.201409121644</version>
            </plugin>
    </pluginMangement>
</build>

我们通过webapp进行的POM与集成测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<properties>
    <sonar.sources>src/main</sonar.sources>
</properties>
<build>
    <finalName>web</finalName>
    <plugins>
        <plugin>
        <groupId>org.mortbay.jetty</groupId>
        jetty-maven-plugin</artifactId>
        <version>8.1.7.v20120910</version>
        <configuration>...</configuration>
        <executions>...</executions>
    </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            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>
            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分析所有模块时,它总是读取相同的coverage数据,并应将它们与当前模块二进制文件中的调试信息对齐。
在maven的分析阶段(mvn声纳:声纳),我们会收到一些不确定它们是否有问题的消息:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    [INFO] [17:30:42.992] Sensor SurefireSensor...
    [INFO] [17:30:42.992] parsing \git\airport-core
est\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
est\..\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
est\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源代码/类,我们得到以下几行:

1
2
3
    [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),我们刚刚添加了"准备代理集成"目标。当然,将其更改为多语言项目。

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

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

  • http://docs.sonarqube.org/display/SONAR/Code+Coverage+by+Integration+Tests+for+Java+Project
  • http://www.sonarqube.org/measure-coverage-by-integration-tests-with-sonar-updated/


我使用了类似的设置,并且在以下配置下一切正常:

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

希望我能帮上忙

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<plugins>
    <plugin>
        <groupId>org.sonarsource.scanner.maven</groupId>
        sonar-maven-plugin</artifactId>
        <version>3.4.0.905</version>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        maven-surefire-plugin</artifactId>

        <executions>
            <execution>
                <phase>test</phase>
            </execution>
        </executions>
        <configuration>
            <!-- the @{argLine} is needed for proper jacoco execution -->
            @{argLine} -Xmx256m</argLine>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.jacoco</groupId>
        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>

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <profile>
      <id>coverage-per-test</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            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>
          sonar-jacoco-listeners</artifactId>
          <version>3.10</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </profile>
  • 将Maven surefire插件更新到最新版本

  • 执行命令:

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

    mvn sonar:sonar
  • 类似于github声纳示例中的描述


    在配置JaCoCo for Jersey时,我有相同的经验。我最终采用了二分法,以便找出哪些模块导致整个项目的代码覆盖率降至0%。

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <profile>
        <id>sonar</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    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>
                    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>
                asm-debug-all</artifactId>
                <optional>false</optional>
            </dependency>
        </dependencies>
    </profile>

    我使用JUnit,在我的情况下,这是因为除JUnit外,我pom.xml中还具有TestNG依赖关系。删除此不必要的依赖关系后,一切都按预期开始工作。


    考虑我想添加的其他答案,这对显示Sonar的测试覆盖范围很重要:

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