如何配置多模块Maven + Sonar + JaCoCo来提供合并的覆盖率报告?

时间:2012-10-23 13:11:38

标签: maven code-coverage sonarqube jacoco

我在互联网上搜索过这个。那里有很多半答案,与${sonar.jacoco.reportPath}org.jacoco:jacoco-maven-plugin:prepare-agent等Maven属性或maven-surefire-plugin设置argLine -javaagent有关。

一些如何,这些答案,无论是单独的还是组合的,都没有产生我正在追求的东西: 一个覆盖率报告,如果在堆栈中更高的测试中使用它,则显示一个被覆盖的类,例如DAO使用的实体,即使它在自己的模块中没有被测试完全覆盖。

在某个地方是否有明确的配置,为了实现这一目标,请?

13 个答案:

答案 0 :(得分:141)

我和你一样处于同样的境地,分散在整个互联网上的半答案非常烦人,因为似乎很多人都有同样的问题,但没有人可以解释他们是如何解决它的。

Sonar docs引用有用的a GitHub project with examples。我解决这个问题的方法是将集成测试逻辑应用于常规单元测试(尽管适当的单元测试应该是子模块特定的,但情况并非总是如此)。

在父pom.xml中,添加以下属性:

<properties>
    <!-- Sonar -->
    <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
    <sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
    <sonar.language>java</sonar.language>
</properties>

这将使Sonar获取同一位置(父项目中的目标文件夹)中所有子模块的单元测试报告。它还告诉Sonar重复使用手动运行的报告,而不是自己滚动。我们只需要为所有子模块运行jacoco-maven-plugin,方法是将它放在父pom中,在build / plugins中:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.0.201210061924</version>
    <configuration>
        <destFile>${sonar.jacoco.reportPath}</destFile>
        <append>true</append>
    </configuration>
    <executions>
        <execution>
            <id>agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
    </executions>
</plugin>

destFile将报告文件放在Sonar查找的位置,append使其附加到文件而不是覆盖它。这将结合同一文件中所有子模块的所有JaCoCo报告。

Sonar将查看每个子模块的文件,因为这是我们在上面指出的内容,为Sonar中的多模块文件提供了组合单元测试结果。

答案 1 :(得分:23)

常见问题

从那时起我就开始对jacoco发疯了。

我的应用服务器(jBoss,Glassfish ..)位于伊拉克,叙利亚,等等。在运行集成测试时是否可以获得多模块覆盖? Jenkins和Sonar也在不同的服务器上。

是。您必须使用在模式output=tcpserver,jacoco ant lib中运行的jacoco agent。基本上是两个jar s。这将使您获得99%的成功。

jacoco代理如何运作?

你追加一个字符串

-javaagent:[your_path]/jacocoagent.jar=destfile=/jacoco.exec,output=tcpserver,address=*

到您的应用程序服务器JAVA_OPTS并重新启动它。在此字符串中,只有{jacocoagent.jar的路径必须替换[your_path],并在运行app服务器的VM上存储(存储它!)。从那时起启动应用服务器,所有部署的应用程序都将被动态监控,并且它们的活动(意味着代码使用)将为您准备好通过tcl请求获取jacocos .exec格式。

我可以重置jacoco代理以便从我的测试开始以来开始收集执行数据吗?

是的,为此,您需要位于jenkins工作区中的jacocoant.jar和ant构建脚本。

基本上我需要的是http://www.eclemma.org/jacoco/,jacocoant.jar位于我的jenkins工作区,jacocoagent.jar位于我的app服务器VM上?

那是对的。

我不想使用蚂蚁,我听说过jacoco maven插件也可以做所有的事情。

这不对,jacoco maven插件可以收集单元测试数据和一些集成测试数据(参见Arquillian Jacoco),但是如果你有例如放心测试作为jenkins中的单独构建,并且想要展示多模块的报道,我无法看到maven插件如何帮助你。

jacoco代理商到底产生了什么?

仅限.exec格式的覆盖数据。声纳然后可以阅读它。

jacoco是否需要知道我的java类所在的位置?

不,声纳确实如此,但不是jacoco。当您执行mvn sonar:sonar课程时,就会发挥作用。

那么蚂蚁脚本呢?

必须在您的jenkins工作区中呈现。我的蚂蚁脚本,我叫它jacoco.xml看起来像这样:

<project name="Jacoco library to collect code coverage remotely" xmlns:jacoco="antlib:org.jacoco.ant">
    <property name="jacoco.port" value="6300"/>
    <property name="jacocoReportFile" location="${workspace}/it-jacoco.exec"/>

    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
        <classpath path="${workspace}/tools/jacoco/jacocoant.jar"/>
    </taskdef>

    <target name="jacocoReport">
            <jacoco:dump address="${jacoco.host}" port="${jacoco.port}" dump="true" reset="true" destfile="${jacocoReportFile}" append="false"/>
    </target>

    <target name="jacocoReset">
            <jacoco:dump address="${jacoco.host}" port="${jacoco.port}" reset="true" destfile="${jacocoReportFile}" append="false"/>
        <delete file="${jacocoReportFile}"/>
    </target>
</project>

调用此脚本时应传递的两个强制参数 -Dworkspace=$WORKSPACE 使用它指向您的jenkins工作区和-Djacoco.host=yourappserver.com主机,而不是http://

另请注意我将jacocoant.jar放入$ {workspace} /tools/jacoco/jacocoant.jar

接下来我该怎么做?

您是否使用jacocoagent.jar启动了应用服务器?

您是否在您的jenkins工作区中放置了ant脚本和jacocoant.jar?

如果是,最后一步是配置jenkins构建。这是策略:

  1. 调用ant目标jacocoReset以重置之前收集的所有数据。
  2. 运行测试
  3. 调用ant目标jacocoReport以获取报告
  4. 如果一切正常,您将在构建工作区中看到it-jacoco.exec

    查看屏幕截图,我在ant目录中的工作区中安装了$WORKSPACE/tools/ant,但您可以使用安装在jenkins中的一个。{1}}。

    enter image description here

    如何在声纳中推送此报告?

    Maven sonar:sonar将完成这项工作(不要忘记配置它),将其指向主pom.xml,以便它将运行所有模块。使用sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.exec参数告知声纳集成测试报告所在的位置。每次分析新的模块类时,它都会在it-jacoco.exec中查找有关覆盖范围的信息。

    我的`target`目录中已经有jacoco.exec,`mvn声纳:声纳`忽略/删除它

    默认mvn sonar:sonar执行clean并删除您的目标目录,请使用sonar.dynamicAnalysis=reuseReports来避免它。

答案 2 :(得分:13)

自0.7.7以来的新方式

从版本0.7.7开始,有一种创建聚合报告的新方法:

您创建了一份单独的报告&#39;收集所有必要报告的项目(聚合器项目中的任何目标都在之前其模块执行,因此无法使用)。

aggregator pom
  |- parent pom
  |- module a
  |- module b
  |- report module 

root pom 看起来像这样(不要忘记在模块下添加新的报告模块):

<build>
<plugins>
  <plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.8</version>
    <executions>
      <execution>
        <id>prepare-agent</id>
        <goals>
          <goal>prepare-agent</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>

每个子模块的poms根本不需要更改。 报告模块中的pom如下所示:

<!-- Add all sub modules as dependencies here -->
<dependencies>
  <dependency>
    <module a>
  </dependency>
  <dependency>
    <module b>
  </dependency>
 ...

  <build>
    <plugins>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.7.8</version>
        <executions>
          <execution>
            <id>report-aggregate</id>
            <phase>verify</phase>
            <goals>
              <goal>report-aggregate</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

可以找到完整的例子here

答案 3 :(得分:9)

我会发布我的解决方案,因为它与其他人略有不同,并且在现有答案的帮助下,让我度过了一个坚实的日子。

对于多模块Maven项目:

ROOT
|--WAR
|--LIB-1
|--LIB-2
|--TEST

WAR项目是主要的网络应用,LIB 1和2是WAR所依赖的附加模块,TEST是集成测试所在的位置。 TEST旋转嵌入式Tomcat实例(不通过Tomcat插件)并运行WAR项目并通过一组JUnit测试对它们进行测试。 WARLIB项目都有自己的单元测试。

所有这一切的结果是整合和单元测试覆盖范围被分离并且能够在SonarQube中进行区分。

ROOT pom.xml

<!-- Sonar properties-->
<sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.language>java</sonar.language>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>

<!-- build/plugins (not build/pluginManagement/plugins!) -->
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.6.201602180812</version>
    <executions>
        <execution>
            <id>agent-for-ut</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <append>true</append>
                <destFile>${sonar.jacoco.reportPath}</destFile>
            </configuration>
        </execution>
        <execution>
            <id>agent-for-it</id>
            <goals>
                <goal>prepare-agent-integration</goal>
            </goals>
            <configuration>
                <append>true</append>
                <destFile>${sonar.jacoco.itReportPath}</destFile>
            </configuration>
        </execution>
    </executions>
</plugin>

WARLIBTEST pom.xml将继承JaCoCo插件执行。

TEST pom.xml

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.19.1</version>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
            <configuration>
                <skipTests>${skip.tests}</skipTests>
                <argLine>${argLine} -Duser.timezone=UTC -Xms256m -Xmx256m</argLine>
                <includes>
                    <includes>**/*Test*</includes>
                </includes>
            </configuration>
        </execution>
    </executions>
</plugin>

我还发现Petri Kainulainens blog post 'Creating Code Coverage Reports for Unit and Integration Tests With the JaCoCo Maven Plugin'对于JaCoCo设置方面很有价值。

答案 4 :(得分:7)

我找到了新的Sonar版本的另一种解决方案,其中不建议使用JaCoCo的二进制报告格式(* .exec),首选格式是XML(SonarJava 5.12和更高版本)。 该解决方案非常简单,并且与先前的解决方案类似,该解决方案在主题为https://stackoverflow.com/a/15535970/4448263的父目录中带有* .exec报告。

假设我们的项目结构为:

moduleC - aggregate project's pom
  |- moduleA - some classes without tests
  |- moduleB - some classes depending from moduleA and tests for classes in both modules: moduleA and moduleB

您需要在聚合项目的pom中执行以下maven构建插件配置:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.5</version>
    <executions>
        <execution>
            <id>prepare-and-report</id>
            <goals>
                <goal>prepare-agent</goal>
                <goal>report</goal>
            </goals>
        </execution>
        <execution>
            <id>report-aggregate</id>
            <phase>verify</phase>
            <goals>
                <goal>report-aggregate</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.basedir}/../target/site/jacoco-aggregate</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

然后使用Maven构建项目:

mvn clean verify

对于Sonar,您应该在管理GUI中设置属性:

sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml,../target/site/jacoco-aggregate/jacoco.xml

或使用命令行:

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

说明

这将在默认目录target/jacoco.exec中为每个模块创建二进制报告。然后在默认目录target/site/jacoco/jacoco.xml中为每个模块创建XML报告。然后在相对于每个模块的父目录的自定义目录${project.basedir}/../target/site/jacoco-aggregate/中为每个模块创建汇总报告。对于模块A和模块B,这将是公用路径moduleC/target/site/jacoco-aggregate/

由于模块B依赖于模块A,因此模块B将最后构建,其报告将在Sonar中用作模块A和B的总覆盖率报告。

除了汇总报告,我们还需要一个普通的模块报告,因为JaCoCo汇总报告仅包含依赖项的覆盖率数据。

这两种类型的报告一起为Sonar提供完整的覆盖率数据。

有一个小限制:您应该能够在项目的父目录中写一个报告(应该有权限)。或者,您可以在根项目的pom.xml(moduleC)中设置属性jacoco.skip=true,并在具有类和测试的模块(moduleA和moduleB)中设置jacoco.skip=false

答案 5 :(得分:5)

我在父级别pom中使用的配置,其中我有单独的单元和集成测试阶段。

我在父POM中配置以下属性 特性

    <maven.surefire.report.plugin>2.19.1</maven.surefire.report.plugin>
    <jacoco.plugin.version>0.7.6.201602180812</jacoco.plugin.version>
    <jacoco.check.lineRatio>0.52</jacoco.check.lineRatio>
    <jacoco.check.branchRatio>0.40</jacoco.check.branchRatio>
    <jacoco.check.complexityMax>15</jacoco.check.complexityMax>
    <jacoco.skip>false</jacoco.skip>
    <jacoco.excludePattern/>
    <jacoco.destfile>${project.basedir}/../target/coverage-reports/jacoco.exec</jacoco.destfile>

    <sonar.language>java</sonar.language>
    <sonar.exclusions>**/generated-sources/**/*</sonar.exclusions>
    <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
    <sonar.coverage.exclusions>${jacoco.excludePattern}</sonar.coverage.exclusions>
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
    <sonar.jacoco.reportPath>${project.basedir}/../target/coverage-reports</sonar.jacoco.reportPath>

    <skip.surefire.tests>${skipTests}</skip.surefire.tests>
    <skip.failsafe.tests>${skipTests}</skip.failsafe.tests>

我将插件定义放在插件管理下。

请注意,我为surefire(surefireArgLine)和failsafe(failsafeArgLine)参数定义了一个属性,以允许jacoco配置javaagent以便在每次测试时运行。

在pluginManagement下

  <build>
     <pluginManagment>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <fork>true</fork>
                    <meminitial>1024m</meminitial>
                    <maxmem>1024m</maxmem>
                    <compilerArgument>-g</compilerArgument>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <forkCount>4</forkCount>
                    <reuseForks>false</reuseForks>
                    <argLine>-Xmx2048m ${surefireArgLine}</argLine>
                    <includes>
                        <include>**/*Test.java</include>
                    </includes>
                    <excludes>
                        <exclude>**/*IT.java</exclude>
                    </excludes>
                    <skip>${skip.surefire.tests}</skip>
                </configuration>
            </plugin>
            <plugin>
                <!-- For integration test separation -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.19.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.19.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <forkCount>4</forkCount>
                    <reuseForks>false</reuseForks>
                    <argLine>${failsafeArgLine}</argLine>
                    <includes>
                        <include>**/*IT.java</include>
                    </includes>
                    <skip>${skip.failsafe.tests}</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>integration-test</id>
                        <goals>
                            <goal>integration-test</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>verify</id>
                        <goals>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <!-- Code Coverage -->
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.plugin.version}</version>
                <configuration>
                    <haltOnFailure>true</haltOnFailure>
                    <excludes>
                        <exclude>**/*.mar</exclude>
                        <exclude>${jacoco.excludePattern}</exclude>
                    </excludes>
                    <rules>
                        <rule>
                            <element>BUNDLE</element>
                            <limits>
                                <limit>
                                    <counter>LINE</counter>
                                    <value>COVEREDRATIO</value>
                                    <minimum>${jacoco.check.lineRatio}</minimum>
                                </limit>
                                <limit>
                                    <counter>BRANCH</counter>
                                    <value>COVEREDRATIO</value>
                                    <minimum>${jacoco.check.branchRatio}</minimum>
                                </limit>
                            </limits>
                        </rule>
                        <rule>
                            <element>METHOD</element>
                            <limits>
                                <limit>
                                    <counter>COMPLEXITY</counter>
                                    <value>TOTALCOUNT</value>
                                    <maximum>${jacoco.check.complexityMax}</maximum>
                                </limit>
                            </limits>
                        </rule>
                    </rules>
                </configuration>
                <executions>
                    <execution>
                        <id>pre-unit-test</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${jacoco.destfile}</destFile>
                            <append>true</append>
                            <propertyName>surefireArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-unit-test</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <configuration>
                            <dataFile>${jacoco.destfile}</dataFile>
                            <outputDirectory>${sonar.jacoco.reportPath}</outputDirectory>
                            <skip>${skip.surefire.tests}</skip>
                        </configuration>
                    </execution>
                    <execution>
                        <id>pre-integration-test</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                        <configuration>
                            <destFile>${jacoco.destfile}</destFile>
                            <append>true</append>
                            <propertyName>failsafeArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-integration-test</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>report-integration</goal>
                        </goals>
                        <configuration>
                            <dataFile>${jacoco.destfile}</dataFile>
                            <outputDirectory>${sonar.jacoco.reportPath}</outputDirectory>
                            <skip>${skip.failsafe.tests}</skip>
                        </configuration>
                    </execution>
                    <!-- Disabled until such time as code quality stops this tripping
                    <execution>
                        <id>default-check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <dataFile>${jacoco.destfile}</dataFile>
                        </configuration>
                    </execution>
                    -->
                </executions>
            </plugin>
            ...

在构建部分

 <build>
     <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>

        <plugin>
            <!-- for unit test execution -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
        </plugin>
        <plugin>
            <!-- For integration test separation -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
        </plugin>
        <plugin>
            <!-- For code coverage -->
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
        </plugin>
        ....

在报告部分

    <reporting>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <version>${maven.surefire.report.plugin}</version>
            <configuration>
                <showSuccess>false</showSuccess>
                <alwaysGenerateFailsafeReport>true</alwaysGenerateFailsafeReport>
                <alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
                <aggregate>true</aggregate>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.plugin.version}</version>
            <configuration>
                <excludes>
                    <exclude>**/*.mar</exclude>
                    <exclude>${jacoco.excludePattern}</exclude>
                </excludes>
            </configuration>
        </plugin>
     </plugins>
  </reporting>

答案 6 :(得分:5)

有一种方法可以实现这一目标。神奇的是创建一个组合的jacoco.exec文件。使用maven 3.3.1,有一种简单的方法可以实现这一目标。在这里我的个人资料:

<profile>
    <id>runSonar</id>
    <activation>
        <property>
            <name>runSonar</name>
            <value>true</value>
        </property>
    </activation>
    <properties>
        <sonar.language>java</sonar.language>
        <sonar.host.url>http://sonar.url</sonar.host.url>
        <sonar.login>tokenX</sonar.login>
        <sonar.jacoco.reportMissing.force.zero>true</sonar.jacoco.reportMissing.force.zero>
        <sonar.jacoco.reportPath>${jacoco.destFile}</sonar.jacoco.reportPath>
        <jacoco.destFile>${maven.multiModuleProjectDirectory}/target/jacoco_analysis/jacoco.exec</jacoco.destFile>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <append>true</append>
                            <destFile>${jacoco.destFile}</destFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.sonarsource.scanner.maven</groupId>
                    <artifactId>sonar-maven-plugin</artifactId>
                    <version>3.2</version>
                </plugin>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>0.7.8</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</profile>

如果您将此个人资料添加到您的父pom并致电mvn clean install sonar:sonar -DrunSonar,您将获得完整的保障。

这里的魔力是maven.multiModuleProjectDirectory。此文件夹始终是您启动maven构建的文件夹。

答案 7 :(得分:2)

ProfileID
    <sonar.language>java</sonar.language>
    <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
    <sonar.jacoco.reportPath>${user.dir}/target/jacoco.exec</sonar.jacoco.reportPath>
    <sonar.jacoco.itReportPath>${user.dir}/target/jacoco-it.exec</sonar.jacoco.itReportPath>
    <sonar.exclusions>
        file:**/target/generated-sources/**,
        file:**/target/generated-test-sources/**,
        file:**/target/test-classes/**,
        file:**/model/*.java,
        file:**/*Config.java,
        file:**/*App.java
    </sonar.exclusions>

答案 8 :(得分:2)

由于声纳sonar.jacoco.reportPathsonar.jacoco.itReportPathsonar.jacoco.reportPaths都为deprecated,因此您现在应该使用sonar.coverage.jacoco.xmlReportPaths。如果要使用Sonar和Jacoco配置多​​模块Maven项目,这也会产生一些影响。

与@Lonzak pointed out一样,自从Sonar 0.7.7开始,您就可以使用Sonars报告聚集目标。只需将以下依赖项放在您的父pom中即可:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.5</version>
    <executions>
        <execution>
            <id>report</id>
            <goals>
                <goal>report-aggregate</goal>
            </goals>
            <phase>verify</phase>
        </execution>
    </executions>
</plugin>

由于jacoco-maven-plugin的当前版本与xml-reports兼容,这将为每个模块在其自己的目标文件夹中创建一个包含{{的站点/ jacoco-aggregate文件夹1}}文件。

要让Sonar组合所有模块,请使用以下命令:

jacoco.xml

为了使我的回答简短而准确,我没有提及mvn -Dsonar.coverage.jacoco.xmlReportPaths=full-path-to-module1/target/site/jacoco-aggregate/jacoco.xml,module2...,module3... clean verify sonar:sonar maven-surefire-plugin依赖性。您可以添加它们而无需任何其他配置:


maven-failsafe-plugin

答案 9 :(得分:1)

您可以在maven上调用名为 merge 的ant任务,将所有覆盖文件(* .exec)放在同一个文件中。

如果您运行单元测试,请使用阶段 prepare-package ,如果您运行集成测试,请使用 post-integration-test

This site举例说明如何在maven项目中调用jacoco ant任务

您可以在声纳上使用此合并文件。

答案 10 :(得分:0)

要进行单元测试和集成测试,您可以使用maven-surefire-plugin和maven-failsafe-plugin以及限制包含/排除。我在与sonar / jacoco取得联系时正在玩CDI,所以我最终参与了这个项目:

https://github.com/FibreFoX/cdi-sessionscoped-login/

也许它对你有所帮助。在我的pom.xml中,我通过在指定的testing-plugins的配置部分中设置argLine-option来隐式使用“-javaagent”。 在MAVEN项目中明确使用ANT是我不会尝试的,对我来说它可以混合两个世界。

我只有一个单模块maven项目,但也许它可以帮助你调整你的工作。

注意:也许并非所有maven-plugins都是up2date,也许某些问题在以后的版本中得到修复

答案 11 :(得分:0)

此示例对我来说效果很好:

<plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.2</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>
                        <!--<excludes>
                            <exclude>com.asimio.demo.rest</exclude>
                            <exclude>com.asimio.demo.service</exclude>
                        </excludes>-->
                        <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>**/*Test.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>
                <includes>
                    <include>**/*IT.java</include>
                </includes>
                <!--<excludes>
                    <exclude>**/*UT*.java</exclude>
                </excludes>-->
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

答案 12 :(得分:0)

Jacoco Wiki 中所述,您还可以生成一个新的报告模块:

<块引用>

策略:具有依赖关系的模块:聚合器的问题 项目可以通过额外的“报告”模块来解决。在一个 多模块 Maven 项目定义了一个单独的模块,不 提供实际内容,但会创建合并的覆盖率报告。它 定义对所有模块的依赖,这些模块应该包含在 合并报告。 “报告”模块将在其之后构建 依赖项并可以访问 exec 文件以及类和 来自它所依赖的项目的源文件。这个策略似乎有效 最好使用当前的 Maven 架构。从用户的角度 有人可能会争辩说,这样一个单独的模块会使构建变得臃肿 定义。或者,单独的模块不能有任何子模块 它可以从中使用 exec 或 class 文件。然而,相比 其他策略这些缺点似乎相当小,可以 以一致的方式处理。

如果您的模块化比具有一些子模块的父模块更复杂,这将特别有用。

您的报告 pom 可能类似于:

 <dependencies>
    <dependency>
        <groupId>org.sonarqube</groupId>
        <artifactId>module1</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.sonarqube</groupId>
        <artifactId>module2</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>report</id>
                    <goals>
                        <goal>report-aggregate</goal>
                    </goals>
                    <phase>verify</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>