Maven插件【测试覆盖率】:jacoco-maven-plugin
目录
参考
# Maven插件【测试覆盖率】:jacoco-maven-plugin
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<configuration>
<skip>${jacoco.skip}</skip>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
</configuration>
<executions>
<execution>
<id>default-instrument</id>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>default-restore-instrumented-classes</id>
<goals>
<goal>restore-instrumented-classes</goal>
</goals>
<configuration>
<!-- <excludes>com/github/dreamhead/moco/*</excludes>-->
</configuration>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
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
# JaCoCo Maven插件配置解析
这个配置是用于jacoco-maven-plugin
插件的配置,该插件是用于Java代码覆盖率分析的Maven插件。下面我将详细解析这个配置的作用、插件功能以及常见使用方式。
# 插件概述
jacoco-maven-plugin
是JaCoCo(Java Code Coverage)工具的Maven集成插件,用于测量Java代码的测试覆盖率。JaCoCo通过字节码插桩技术,在运行时收集代码执行信息,生成详细的覆盖率报告,包括行覆盖率、分支覆盖率、方法覆盖率等指标。
# 配置解析
# 基本配置部分
<configuration>
<skip>${jacoco.skip}</skip>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
</configuration>
2
3
4
skip
: 控制是否跳过JaCoCo的执行,值来自Maven属性${jacoco.skip}
,通常用于在特定情况下禁用覆盖率分析dataFile
: 指定覆盖率数据文件的存储路径,默认为target/jacoco.exec
# 执行(executions)部分
配置中定义了三个执行目标:
instrument目标:
<execution> <id>default-instrument</id> <goals> <goal>instrument</goal> </goals> </execution>
1
2
3
4
5
6- 对字节码进行插桩,插入额外的指令用于跟踪代码执行情况
- 这是JaCoCo实现覆盖率分析的核心步骤
restore-instrumented-classes目标:
<execution> <id>default-restore-instrumented-classes</id> <goals> <goal>restore-instrumented-classes</goal> </goals> </execution>
1
2
3
4
5
6- 恢复被插桩的类文件到原始状态
- 注释掉的
excludes
配置可用于排除特定包或类不参与覆盖率分析
report目标:
<execution> <id>default-report</id> <goals> <goal>report</goal> </goals> </execution>
1
2
3
4
5
6- 生成覆盖率报告,默认生成HTML格式报告
- 报告会基于
.exec
文件中的数据,结合源代码和编译后的字节码生成
# 插件的主要功能
- prepare-agent: 配置JVM代理以收集覆盖率数据(此配置中未显式出现,但常用)
- instrument: 对字节码进行插桩处理
- restore-instrumented-classes: 恢复原始类文件
- report: 生成可视化覆盖率报告
- check: 检查覆盖率是否达到阈值(此配置中未使用)
- merge: 合并多个覆盖率数据文件
- dump: 请求远程JVM的覆盖率数据转储
# 典型使用场景
# 1. 基本使用流程
- 将插件配置添加到项目的
pom.xml
中 - 运行测试:
mvn clean test
- 这会自动执行插桩并收集覆盖率数据 - 生成报告:
mvn verify
- 这会触发report目标生成报告 - 查看报告: 在
target/site/jacoco
目录下查看HTML报告
# 2. 多模块项目
对于多模块项目,可以在父POM中使用report-aggregate
目标合并各子模块的覆盖率数据:
<execution>
<id>report-aggregate</id>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
2
3
4
5
6
# 3. 设置覆盖率阈值
可以配置check
目标来设置最低覆盖率要求,未达标时构建失败:
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 4. 排除特定类/包
可以通过excludes
配置排除不需要分析覆盖率的代码:
<configuration>
<excludes>
<exclude>com/example/legacy/**</exclude>
</excludes>
</configuration>
2
3
4
5
# 高级用法
- 与CI/CD集成: 可以将JaCoCo与Jenkins等CI工具集成,实现自动化覆盖率检查和报告
- 分离单元测试和集成测试覆盖率: 可以为不同类型的测试生成独立的覆盖率报告
- 命令行工具: 除了Maven插件,JaCoCo还提供CLI工具(jacococli.jar)用于非Maven项目
# 注意事项
- JaCoCo需要与测试框架(如JUnit)和测试执行插件(如maven-surefire-plugin)配合使用
- 插桩可以在编译时(offline)或运行时(on-the-fly)进行,Maven插件通常使用后者
- 对于大型项目,可能需要调整JVM内存设置以确保覆盖率分析顺利进行
通过合理配置jacoco-maven-plugin,开发者可以有效地监控测试覆盖率,提高代码质量,并集成到自动化构建流程中。
# JaCoCo插件在多模块项目中如何配置才能正确统计整体覆盖率?
# JaCoCo在多模块项目中配置整体覆盖率统计的完整指南
JaCoCo(Java Code Coverage)是Java项目中广泛使用的代码覆盖率工具,在多模块项目中正确配置JaCoCo以实现整体覆盖率统计需要特别注意一些关键点。下面我将详细介绍多模块项目中JaCoCo的配置方法和最佳实践。
# 一、基础配置:父模块设置
在多模块项目中,首先应该在父模块的pom.xml中进行JaCoCo的基础配置,确保所有子模块能够继承这些配置。
<!-- 父模块pom.xml中的配置 -->
<properties>
<jacoco.version>0.8.10</jacoco.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
这段配置做了以下工作:
- 定义了JaCoCo的版本属性
- 在pluginManagement中配置了jacoco-maven-plugin
- 设置了prepare-agent目标,用于在测试运行时收集覆盖率数据
# 二、子模块配置
每个需要统计覆盖率的子模块需要在pom.xml中引入JaCoCo插件:
<!-- 子模块pom.xml中的配置 -->
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2
3
4
5
6
7
8
9
# 三、聚合报告配置
为了生成整个项目的汇总覆盖率报告,需要在父模块或专门的聚合模块中添加report-aggregate目标配置:
<!-- 父模块或聚合模块pom.xml中的配置 -->
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
report-aggregate目标会收集所有子模块的覆盖率数据(.exec文件)并生成一个汇总报告。
# 四、完整配置示例
一个完整的父模块配置可能如下所示:
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
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
# 五、执行命令
配置完成后,可以通过以下命令生成覆盖率报告:
生成各子模块独立报告:
mvn clean test
1各子模块的报告会生成在
target/site/jacoco/index.html
生成聚合报告:
mvn clean verify
1聚合报告会生成在父模块的
target/site/jacoco-aggregate/index.html
# 六、高级配置选项
# 1. 设置覆盖率阈值
可以配置check目标来设置最低覆盖率要求:
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2. 排除特定类或包
可以通过excludes配置排除不需要分析覆盖率的代码:
<configuration>
<excludes>
<exclude>**/generated/**</exclude>
<exclude>**/model/*</exclude>
</excludes>
</configuration>
2
3
4
5
6
# 3. 合并规则配置
对于多模块项目,可能需要更详细的合并配置:
<execution>
<id>merge-results</id>
<phase>verify</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<fileSets>
<fileSet>
<directory>module-a/target</directory>
<includes>
<include>*.exec</include>
</includes>
</fileSet>
<fileSet>
<directory>module-b/target</directory>
<includes>
<include>*.exec</include>
</includes>
</fileSet>
</fileSets>
</configuration>
</execution>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 七、常见问题与解决方案
- 报告为空:检查测试是否实际执行,确保测试覆盖了目标代码
- 无法生成汇总报告:检查各子模块的target目录中是否存在.exec文件,确认合并配置正确
- 版本冲突:统一在父模块中定义JaCoCo插件版本,避免子模块使用不同版本
- 路径问题:在多模块项目中,特别注意文件路径的配置,确保能正确找到各模块的.exec文件
# 八、与CI/CD集成
JaCoCo可以轻松集成到CI/CD流程中:
- 在Jenkins等CI工具中配置JaCoCo报告收集
- 设置覆盖率阈值作为质量门禁
- 将报告与SonarQube等代码质量平台集成
示例Jenkins配置:
stage('Test') {
steps {
sh 'mvn clean verify'
}
}
stage('Jacoco Report') {
steps {
jacoco execPattern: '**/target/jacoco.exec'
}
}
2
3
4
5
6
7
8
9
10
# 九、最佳实践建议
- 统一版本管理:在父模块中统一管理JaCoCo版本
- 合理设置阈值:根据项目实际情况设置合理的覆盖率阈值
- 定期检查报告:将覆盖率检查作为代码审查的一部分
- 排除生成代码:避免统计自动生成代码的覆盖率
- 模块化配置:对于大型项目,考虑按功能模块分组统计覆盖率
通过以上配置和实践,可以在多模块项目中正确统计整体代码覆盖率,帮助团队提高代码质量和测试有效性。
# 在多模块项目中,如何排除某些子模块不参与覆盖率统计?
# 多模块项目中排除特定子模块的JaCoCo覆盖率统计方法
在大型多模块项目中,有时需要排除某些子模块不参与代码覆盖率统计,例如自动生成的代码模块、第三方库封装模块或测试工具模块等。以下是几种在不同构建工具中实现这一目标的详细方法:
# 一、Maven项目排除方法
# 1. 通过插件配置排除特定模块
在父pom.xml中配置jacoco-maven-plugin时,可以通过skip
属性或excludes
配置来排除特定模块:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions>
<execution>
<id>report-aggregate</id>
<configuration>
<!-- 排除特定模块 -->
<excludes>
<exclude>**/generated/**</exclude>
<exclude>com/example/excluded/**</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
对于整个模块的排除,可以在特定子模块的pom.xml中添加:
<properties>
<jacoco.skip>true</jacoco.skip>
</properties>
2
3
这样该模块将完全跳过JaCoCo的覆盖率统计。
# 2. 使用独立聚合模块
创建一个专门用于生成覆盖率报告的聚合模块,在该模块中只依赖需要统计覆盖率的模块:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>module-to-include-1</artifactId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>module-to-include-2</artifactId>
</dependency>
<!-- 不添加需要排除的模块依赖 -->
</dependencies>
2
3
4
5
6
7
8
9
10
11
这种方法通过控制模块依赖关系来间接排除不需要统计的模块。
# 二、Gradle项目排除方法
# 1. 全局配置排除
在根项目的build.gradle中,可以为所有子项目配置JaCoCo并设置排除规则:
subprojects {
plugins.withType(JavaPlugin) {
if (!project.name.equals('module-to-exclude')) {
apply plugin: 'jacoco'
jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'**/generated/**',
'com/example/excluded/**'
])
}))
}
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 2. 模块级排除
在需要排除的模块build.gradle中直接禁用JaCoCo:
test {
jacoco {
enabled = false
}
}
2
3
4
5
或者更彻底地跳过测试任务:
tasks.withType(Test) {
enabled = false
}
2
3
这样可以完全排除该模块的覆盖率统计。
# 三、Android项目特殊处理
对于Android多模块项目,除了上述方法外,还需要注意:
# 1. 排除特定包或类
android {
testOptions {
unitTests.all {
jacoco {
excludes = [
'android/**',
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*'
]
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2. 处理debug编译类型
由于Android默认使用release编译,需要确保被统计模块使用debug编译:
debug {
testCoverageEnabled = true
}
2
3
同时排除模块可以保持release编译。
# 四、高级排除技巧
# 1. 基于文件模式的排除
可以使用Ant风格路径表达式排除特定模式的文件:
**/generated/** # 排除所有generated目录下的文件
**/*Test.class # 排除所有测试类
**/*$*.class # 排除所有匿名内部类
2
3
# 2. 动态排除
通过Gradle的afterEvaluate可以在配置阶段动态决定排除内容:
jacocoTestReport {
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it, exclude: customExcludes)
}))
}
}
2
3
4
5
6
7
# 五、验证排除效果
配置完成后,可以通过以下步骤验证排除是否生效:
运行测试并生成报告:
# Maven mvn clean test jacoco:report # Gradle gradle test jacocoTestReport
1
2
3
4
5查看生成的报告:
- Maven项目报告位于
target/site/jacoco/
或target/site/jacoco-aggregate/
- Gradle项目报告位于
build/reports/jacoco/
- Maven项目报告位于
检查报告中是否确实不包含排除的模块或类。
# 六、常见问题解决
- 排除不生效:检查排除模式是否正确,特别是路径分隔符使用
/
而非\
- 报告为空:确保测试实际执行,且被统计模块正确配置了JaCoCo
- 多模块依赖问题:当A模块依赖B模块,但想排除B模块时,需要确保A模块的测试不依赖B模块的实现
通过以上方法,可以灵活地控制多模块项目中哪些模块参与覆盖率统计,从而得到更准确、更有意义的覆盖率报告。