如何配置多模块Maven +声纳+ JaCoCo给合并后的覆盖报告?(How to configur

2019-06-18 15:00发布

我已经搜查向上和向下的互联网这一个。 有很多半的答案在那里,与Maven的特性,如做${sonar.jacoco.reportPath} ,或org.jacoco:jacoco-maven-plugin:prepare-agent或设置maven-surefire-plugin argLine-javaagent

一些如何,没有回答这些问题,无论是对自己,或者组合,是生产什么我后:覆盖报告,其中显示了一个类所涵盖,如果它在测试更高的堆栈使用,如使用实体通过DAO的,即使它不能完全由它自己的模块中的测试覆盖。

是否有一个明确的配置的地方,要实现这一点,好吗?

Answer 1:

我是在同样的情况你,散布在互联网上一半的答案是很烦人的,因为它似乎是很多人有同样的问题,但没有人可以打扰,充分说明他们是如何解决它。

该声纳的文档是指一个GitHub的项目,例子是有帮助的。 我做了什么来解决这个是集成测试逻辑应用到普通的单元测试(虽然适当的单元测试应该是具体的子模块,这是情况并非总是如此)。

在父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>

这将使声纳拿起在同一个地方的所有子模块的单元测试报告(在父项目中的目标文件夹)。 它还告诉声纳重用报告手动运行滚动自己的,而不是。 我们只需要通过将该父POM,构建/插件内,使所有子模块jacoco - Maven的插件运行:

<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会将报告文件中的地方,声纳将寻找并append使其追加到该文件,而不是覆盖它。 本文将结合所有JaCoCo在同一文件中的所有子模块报告。

声纳将看文件每个子模块,因为这就是我们指出了他在上面,使我们在声纳多模块文件合并单元测试结果。



Answer 2:

常问问题

从自那时以来,我疯了与jacoco我的头顶部的问题。

我的应用程序服务器(JBoss和Glassfish的..)位于伊拉克,叙利亚,无论..是否有可能在其上运行的集成测试时,得到的多模块覆盖? 詹金斯和声纳也都在不同的服务器上。

是。 你必须使用jacoco剂 ,在模式运行output=tcpserver ,jacoco蚂蚁库。 基本上有两个jar秒。 这会给你99%的成功。

如何jacoco剂的工作原理?

你追加一个字符串

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

在应用服务器JAVA_OPTS并重新启动它。 在此字符串只[your_path]必须与你的虚拟机,其中应用服务器运行路径jacocoagent.jar,存储(存储它!)来代替。 自那时以来,启动应用程序服务器,所部署的所有应用程序将被动态监测和他们的活动(意为代码的用法)将随时为您在jacocos .exec格式由TCL请求得到。

我可以重置jacoco剂只启动以来,时间在我的测试开始收集执行数据?

是的,为此你需要jacocoant.jar,位于您的工作空间詹金斯Ant构建脚本。

所以基本上我从http://www.eclemma.org/jacoco/需要的是jacocoant.jar位于我詹金斯工作区,jacocoagent.jar位于我的应用程序服务器虚拟机上?

那就对了。

我并不想用蚂蚁,我听说jacoco Maven插件可以做所有的事情太多。

这是不对的,jacoco Maven插件可以采集单元的测试数据和一些集成测试数据(见的Arquillian Jacoco ),但如果你有例如放心测试,在詹金斯一分开构建,并且要显示多模块的覆盖,我可以“看不到插件如何Maven可以帮助你。

究竟jacoco剂生产什么?

只有在覆盖数据.exec格式。 声纳则可以读取它。

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

不,不声纳,但并不jacoco。 当你这样做mvn sonar:sonar路径类的用武之地。

那么,关于ant脚本?

它在你的詹金斯工作空间呈现。 矿ant脚本,我把它叫做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>

两个强制性PARAMS调用此脚本时,你应该通过-Dworkspace=$WORKSPACE用它来指向您的詹金斯的工作区和-Djacoco.host=yourappserver.com主机,而无需http://

还要注意,我把我的jacocoant.jar为$ {}工作区/tools/jacoco/jacocoant.jar

我应该怎么做?

什么时候开始你的应用服务器与jacocoagent.jar?

你把Ant脚本和jacocoant.jar在你的工作空间詹金斯?

如果是最后一个步骤是配置詹金斯建设。 这里是策略:

  1. 调用Ant目标jacocoReset重置所有之前收集的数据。
  2. 运行测试
  3. 调用Ant目标jacocoReport拿到报告

如果一切是正确的,你会看到it-jacoco.exec在您的构建工作空间。

看截图,我也有ant安装在我的工作区$WORKSPACE/tools/ant目录,但您可以使用一个安装在您的詹金斯。

如何在声纳本报告推?

Maven的sonar:sonar将做的工作(不要忘记进行配置),将其指向主要的pom.xml那么它会通过所有模块运行。 使用sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.exec参数来告诉声纳在您的集成测试报告所在。 每当它会分析新的模块课程,它会寻找有关报道中的信息it-jacoco.exec

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

默认情况下, mvn sonar:sonar确实clean ,并删除你的目标目录,使用sonar.dynamicAnalysis=reuseReports避免。



Answer 3:

NEW WAY自版本0.7.7

由于0.7.7版本有创建一个汇总报告的新方式:

您创建一个单独的“报告”项目,该项目收集(在聚合项目之前,它的模块中执行,因此它不能用于任何目的)的所有必要的报告。

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

根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>

从各子模块的劲歌并不需要在所有改变。 从报表模块的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>

全exmple可以发现在这里 。



Answer 4:

我会后我的解决方案,因为它是从别人略有不同,也花了我一天固体得到正确,与现有的答案的援助。

对于多模块Maven项目:

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

WAR项目是主要的Web应用程序, 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>

我还发现彼得Kainulainens博客文章“创建代码覆盖率报告的单元和集成测试随着JaCoCo Maven插件”是对事物的JaCoCo设置侧有价值。



Answer 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>

我把插件管理下的插件定义。

请注意,我定义万无一失属性(surefireArgLine)和故障安全(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>


Answer 6:

有一种方法可以做到这一点。 神奇的是建立一个联合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构建的文件夹。



Answer 7:

    <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>

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.9</version>
                <executions>
                    <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${sonar.jacoco.reportPath}</destFile>
                            <append>true</append>
                            <propertyName>surefire.argLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>default-prepare-agent-integration</id>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                        <configuration>
                            <destFile>${sonar.jacoco.itReportPath}</destFile>
                            <append>true</append>
                            <propertyName>failsafe.argLine</propertyName>
                        </configuration>
                    </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>             


Answer 8:

你可以打电话叫蚂蚁任务合并的行家,把所有的覆盖文件(* .exec)一起在同一个文件。

如果您正在运行单元测试使用阶段作准备包 ,如果您运行集成测试,以便使用后的整合测试

这个网站有一个例子,如何调用Maven项目jacoco Ant任务

您可以在声呐使用该合并的文件。



Answer 9:

有单元测试和集成,测试,你可以使用Maven的万无一失,插件和Maven故障保护,插件与限制包含/排除。 我与CDI播放,而在声纳/ jacoco取得联系,所以我在这个项目结束了:

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

也许它可以帮助你一点点。 在我的pom.xml我用“-javaagent”通过设置指定的测试 - 插件的配置 - 部分argLine选项隐含的。 在Maven项目明确使用ANT事情我不会多到混合两个世界给一个尝试,对我来说它。

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

注意:也许不是所有的Maven的插件up2date的,也许有些问题是固定的更高版本



文章来源: How to configure multi-module Maven + Sonar + JaCoCo to give merged coverage report?