JDK多版本集成 Jacoco 配置指南
本篇相关 JDK 版本配置如下:
-
JDK8
-
JDK11
-
JDK17
Jacoco 是什么
Jacoco 是一个用于Java程序的代码覆盖率报告工具。它通过动态分析(在代码执行时收集数据)来生成代码覆盖率
报告文件。Jacoco 支持多种覆盖率标准,包括行覆盖率、分支覆盖率和复杂度覆盖率。
代码覆盖率
代码覆盖率是指单元测试覆盖了多少程序代码,是评估测试的有效性和代码质量的关键指标。
代码覆盖率的重要性
-
质量保证:代码覆盖率是衡量软件测试完整性的关键指标。高覆盖率意味着代码的大部分都经过了测试,减少了出错的可能性。
-
发现未测代码:通过查看覆盖率报告文件能够识别哪些代码没有被测试到,从而可以针对性地增加测试用例。
-
重构和维护:
假如某一个方法不能单测,那么说明这个方法是需要重构的。
在重构过程中,高覆盖率有助于减少引入新错误的风险。
为什么要用 Jacoco
-
易于集成:Jacoco 可以集成到Java项目中,支持Maven、Gradle等构建工具。
-
非侵入式:Jacoco 在运行时收集信息,无需修改代码。
-
多种覆盖率指标:Jacoco 提供了行覆盖、分支覆盖等多种覆盖率指标。
-
生成详细报告:能生成单测覆盖率报告,浏览器打开index.html即可看到哪些代码被覆盖,整体覆盖率多少等。
JDK8 集成 Jacoco 生成单测覆盖率报告
版本
-
Java:8
-
Spring Boot:2.2.2.RELEASE
-
Jacoco:0.8.10
父pom.xml
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
静态Mock依赖,用于测试静态方法
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>2.0.9</version>
</dependency>
Tips:powermock 2.0.9 版本不能与 junit5 集成。
父pom.xml
插件配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<!-- 执行单测 -->
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${org.jacoco.version}</version>
<configuration>
<includes>
<include>com/**/*</include>
</includes>
</configuration>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
子pom.xml
启动类构建配置
<build>
<finalName>项目名</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${org.jacoco.version}</version>
<executions>
<execution>
<id>report-aggregate</id>
<phase>test</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
单元测试代码必须写在如下工程目录:src/test/java
,不允许写在业务代码目录下。源码构建时会跳过此目录,而单元测试框架默认是扫描此目录。
单测怎么写,参考之前的文章:Mockito单测之道
运行命令生成单测报告:mvn test。
在项目编译后的 target 文件夹中找到生成单测覆盖率报告文件:index.html
点击可以看到覆盖率相关参数:
指标参数解释:
- Instructions(指令):
-
指令覆盖率是基于最低级别的代码执行——Java字节码指令。即使一行代码包含了多个Java字节码指令,这些指令可能会部分被执行。
-
- Branches(分支):
-
衡量在条件语句(如
if
和switch
)中执行的分支数。用于评估条件语句的覆盖程度。
-
- Cyclomatic Complexity(圈复杂度):
-
测试用例覆盖了多少种可能的执行路径或决策点(如if条件、循环等)。
-
- Lines(行):
-
有多少行代码被测试用例执行过。
-
- Methods(方法):
-
检查类中的每个方法是否至少被测试用例执行过一次。
-
- Classes(类):
-
如果一个类中至少有一个方法被测试覆盖,那么这个类就被认为是覆盖的。
-
JDK11 集成 Jacoco 生成单测覆盖率报告
版本
-
Java:11
-
Spring Boot:2.2.2.RELEASE
-
Jacoco:0.8.10
配置调整较少,但对应的单测代码需要微调。
父pom.xml
插件配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<!-- 执行单测 -->
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${org.jacoco.version}</version>
<configuration>
<includes>
<include>com/**/*</include>
</includes>
</configuration>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
子pom.xml
启动类构建配置
<build>
<finalName>mgt-system-web</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${org.jacoco.version}</version>
<executions>
<execution>
<id>report-aggregate</id>
<phase>test</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
JDK17 集成 Jacoco 生成单测覆盖率报告
版本
-
Java:17
-
Spring Boot:3.0.2
-
Jacoco:0.8.10
父pom.xml
插件配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.xinluo.flup.FlupDddApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${org.jacoco.version}</version>
<configuration>
<includes>
<include>com/**/*</include>
</includes>
</configuration>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<!-- 打包xml -->
<resources>
<resource>
<directory>src/main/java</directory>
<filtering>false</filtering>
<includes>
<include>**/xml/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
子pom.xml
启动类构建配置
<build>
<finalName>flup-web</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${org.jacoco.version}</version>
<executions>
<execution>
<id>report-aggregate</id>
<phase>test</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
总结
上述JDK8、JDK11 版本配置均能在 Jenkins 上集成单测。有个注意的点是:本地 JDK 版本应和 Jenkins 上配置的 JDK 版本一致。
从实战来看,编写单测的时间不亚于编码的时间,但从长远来看,对于整个软件的开发过程是有益的。单测也是确保代码质量和可维护性的关键工具。
Jacoco 在不同版本的 JDK 上的兼容性和在 Jenkins 上的集成能力成为我们优先考虑的覆盖率工具。从公司领导的角度来看,他们也需要这样的覆盖率指标来看单测标准的落地情况。然而,作为技术人员,我们不是为了堆覆盖率完成覆盖率数值的增长。在我来看,其本质还是通过单测(自测)提前发现问题,减少bug,尽量的去避免将来可能出现的生产事故。
参考资料
-
Jacoco官网:https://www.jacoco.org/