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

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

maven-surefire-plugin

jacoco-maven-plugin

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

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

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


    
        org.apache.maven.plugins
        maven-surefire-plugin
        2.18.1
        
            false
            true
        
    
    
        org.jacoco
        jacoco-maven-plugin
        0.8.5
        
            
                my-prepare-agent
                
                    prepare-agent
                
            
            
                my-report
                test
                
                    report
                
            
        
    

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

├── 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中都重复添加同样的内容)


    
        org.apache.maven.plugins
        maven-surefire-plugin
        2.18.1
        
            false
            true
        
    
    
        org.jacoco
        jacoco-maven-plugin
        0.8.5
        
            
                my-prepare-agent
                
                    prepare-agent
                
            
        
    

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


    
        org.jacoco
        jacoco-maven-plugin
        0.8.5
        
            
                my-report
                test
                
                    report-aggregate
                
            
        
    

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

  
    
      @project.groupId@
      module1
      ${project.version}
    
    
      @project.groupId@
      module2
      ${project.version}
    
    
      @project.groupId@
      module3
      ${project.version}
    
 

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

springboot多模块工程单元测试jacoco统计代码覆盖率总结_第1张图片搜索了很多文章都无解,最后查看jacoco的help才找到答案:

这里需要涉及另外一个插件:maven-surefire-plugin

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

原理分析:jacoco在prepare-agent阶段会生成一个属性,这个属性指向jacoco的runtime agent,默认这个属性叫argLine,我们需要在maven-surefire-plugin的配置中,引用这个属性,这样在surefire执行测试时,才会能够找到并挂载jacoco的agent,从而实现代码覆盖率的统计(当然我们也可以自定义这个属性的名字)

        
          ${argLine}
        

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


    
        org.apache.maven.plugins
        maven-surefire-plugin
        2.18.1
        
            false
            true
            ${argLine}
        
    
    
        org.jacoco
        jacoco-maven-plugin
        0.8.5
        
            
                my-prepare-agent
                
                    prepare-agent
                
            
        
    

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


    
        org.apache.maven.plugins
        maven-surefire-plugin
        2.18.1
        
            false
            true
            ${jacocoArgLine}
        
    
    
        org.jacoco
        jacoco-maven-plugin
        0.8.5
        
            
                my-prepare-agent
                
                    prepare-agent
                
                
                  jacocoArgLine
                
            
        
    

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

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:
  
   
   org.apache.maven.plugins
   maven-surefire-plugin
   
   @{argLine} -your -extra -arguments
   

   

  
  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:
  
   
   -your -extra -arguments
   

   ...
   
   org.apache.maven.plugins
   maven-surefire-plugin
   
   
   

   

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

你可能感兴趣的:(技术,质量,spring,boot,代码覆盖率,java)