0


springboot多模块工程单元测试jacoco统计代码覆盖率总结

jacoco统计代码覆盖率的文章一搜一大堆,方法也很简单,就是在pom中引用两个插件:

maven-surefire-plugin

jacoco-maven-plugin

其中jacoco-maven-plugin的关键配置为要有两个execution:

一个goal是prepare-agent,即准备agent,实现为代码插桩

一个goal是report,顾名思义,即生成覆盖率报告

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
            <skipTests>false</skipTests>
            <testFailureIgnore>true</testFailureIgnore>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.5</version>
        <executions>
            <execution>
                <id>my-prepare-agent</id>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
            </execution>
            <execution>
                <id>my-report</id>
                <phase>test</phase>
                <goals>
                    <goal>report</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

但是如果是多模块的工程呢?如下面的结构:

├── module1
│ └── pom.xml
├── module2
│ └── pom.xml
├── module3
│ └── pom.xml
├── pom.xml

每个模块都这么配置的话,生成的报告是各自独立的,即会生成3个报告,那么怎么把各个模块的代码覆盖率统计在一起,生成一个聚合的报告呢?

可以参考七个披萨的博客,我觉得他的这篇文章写的特别好,强烈推荐读一下:jacoco插件配置生成单元测试覆盖率报告_七个披萨的博客-CSDN博客_jacoco:report-aggregate

我在这里复述一下其给出的做法:

jacoco提供了报告聚合的能力(goal为report-aggregate,注意与上面提到的report的区别),这就需要有一个模块来做报告聚合,这个模块需要引用所有的其他模块(以上面举例的工程为例,这个模块可以是新增的module4,也可以在module1/2/3中任选一个,一般在多模块的工程中,都会有一个主模块做为启动模块,可以用这个启动模块来做jacoco的报聚合)

划一下重点:

  1. 一个模块配置jacoco的report-aggregate
  2. 这个模块需要引用所有的其他模块

具体做法如下:

第一:在项目根目录下的父pom中添加jacoco-maven-plugin,并配置goal是prepare-agent(这么做的好处是不用在每个module的pom中都重复添加同样的内容)

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
            <skipTests>false</skipTests>
            <testFailureIgnore>true</testFailureIgnore>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.5</version>
        <executions>
            <execution>
                <id>my-prepare-agent</id>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

第二:在聚合模块中配置jacoco聚合报告:

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

第三:在聚合模块中引用其他模块(非常重要,只有引用的模块的覆盖率才会被聚合到报告中,未引用的模块的覆盖率不会被收集和聚合):

  <dependencies>
    <dependency>
      <groupId>@project.groupId@</groupId>
      <artifactId>module1</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>@project.groupId@</groupId>
      <artifactId>module2</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>@project.groupId@</groupId>
      <artifactId>module3</artifactId>
      <version>${project.version}</version>
    </dependency>
 </dependencies>

但是我按照上述文章提到的方法配置后,可以得到聚合的报告了,但是覆盖率都为0,这又是怎么回事呢?

搜索了很多文章都无解,最后查看jacoco的help才找到答案:

需要在maven-surefire-plugin中配置引用jacoco的输出属性argLine

jacoco在prepare-agent阶段会生成一个属性指向jacoco的runtime agent,默认这个属性叫argLine,我们需要在maven-surefire-plugin的配置中,引用这个属性(当然我们也可以自定义这个属性的名字,那么就需要在maven-surefire-plugin的配置中引用我们自定义的属性名)

        <configuration>
          <argLine>${argLine}</argLine>
        </configuration>

最终在根目录的pom.xml是这样的

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
            <skipTests>false</skipTests>
            <testFailureIgnore>true</testFailureIgnore>
            <argLine>${argLine}</argLine>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.5</version>
        <executions>
            <execution>
                <id>my-prepare-agent</id>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

或者在prepare-agent阶段自定义jacoco输出的属性名,那么你的根pom文件是这样的:

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18.1</version>
        <configuration>
            <skipTests>false</skipTests>
            <testFailureIgnore>true</testFailureIgnore>
            <argLine>${jacocoArgLine}</argLine>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.5</version>
        <executions>
            <execution>
                <id>my-prepare-agent</id>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
                <configuration>
                  <propertyName>jacocoArgLine</propertyName>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>

好了,这时再去运行一下:

mvn test -Dmaven.test.failure.ignore=true

看看聚合报告的结果吧。

jacoco帮助命令行提示原文如下,有兴趣的英文好的同学可以看看

jacoco:prepare-agent
Prepares a property pointing to the JaCoCo runtime agent that can be passed as
a VM argument to the application under test. Depending on the project
packaging type by default a property with the following name is set:

  • tycho.testArgLine for packaging type eclipse-test-plugin and
  • argLine otherwise.

If your project already defines VM arguments for test execution, be sure that
they will include property defined by JaCoCo.

One of the ways to do this in case of maven-surefire-plugin - is to use syntax
for late property evaluation:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>@{argLine} -your -extra -arguments</argLine>
</configuration>
</plugin>

You can define empty property to avoid JVM startup error Could not find or
load main class @{argLine} when using late property evaluation and
jacoco-maven-plugin not executed.

Another way is to define 'argLine' as a Maven property rather than as part of
the configuration of maven-surefire-plugin:

<properties>
<argLine>-your -extra -arguments</argLine>
</properties>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- no argLine here -->
</configuration>
</plugin>

Resulting coverage information is collected during execution and by default
written to a file when the process terminates.


本文转载自: https://blog.csdn.net/boweiqiang/article/details/128559724
版权归原作者 boweiqiang 所有, 如有侵权,请联系我们删除。

“springboot多模块工程单元测试jacoco统计代码覆盖率总结”的评论:

还没有评论