文章目录
- 简介
- 开始集成
- 1、pom添加依赖
- 2、pom添加插件
- 3、业务代码
- 4、单元测试代码
- 5、开始测试
- 6、查看结果
- 如何排除不需要的路径?
- 设置覆盖率目标并验证
- JACOCO的不足
- JACOCO改进版super-Jacoco
- 代码覆盖率的知识扩展
简介
JaCoCo(Java Code Coverage)是一个开源的Java代码覆盖率工具,它主要用于评估Java程序的测试完整性。通过跟踪测试过程中执行的代码,JaCoCo能够提供多种覆盖率指标,帮助开发者确保代码的测试质量。这些指标包括指令覆盖、分支覆盖、圈复杂度、行覆盖、方法覆盖和类覆盖。
开始集成
1、pom添加依赖
<!-- 代码覆盖率 -->
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.12</version>
<scope>test</scope>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.8.0</version>
<scope>test</scope>
</dependency>
2、pom添加插件
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.12</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
3、业务代码
下面是一段用于单元测试的测试代码
public class UnitTestServiceImpl implements UnitTestService {
@Override
public void compareTime() {
LocalDate date1 = LocalDate.of(2024, 1, 1);
LocalDate date2 = LocalDate.of(2024, 12, 31);
int result = date1.compareTo(date2);
if (result < 0) {
System.out.println("date1 在 date2 之前");
} else if (result == 0) {
System.out.println("date1 和 date2 相同");
} else {
System.out.println("date1 在 date2 之后");
}
// 使用 isBefore 方法
if (date1.isBefore(date2)) {
System.out.println("date1 在 date2 之前");
}
// 使用 isAfter 方法
if (date1.isAfter(date2)) {
System.out.println("date1 在 date2 之后");
}
// 使用 equals 方法
if (date1.equals(date2)) {
System.out.println("date1 等于 date2 ");
}
}
}
4、单元测试代码
@RunWith(MockitoJUnitRunner.class)
public class TestTaskService {
@InjectMocks
private UnitTestServiceImpl unitTestService;
@Test
public void testOne() {
unitTestService.compareTime();
}
}
5、开始测试
编译项目运行单元测试
6、查看结果
测试完成后, target/site/jacoco/index.html 可以查看报告结果。
1、打开报告后找到自己的测试的service,从下图可以看出UnitTestService ,里面代码已经覆盖了 72%,分支已经覆盖了 40% 。
2、点进UnitTestServiceImpl.java
Jacoco 在这里非常清楚地展示了不同级别的覆盖范围。它使用不同颜色的菱形图标来表示分支的代码覆盖率。并使用背景颜色来表示行的代码覆盖率。
- 绿色菱形表示所有分支均已被覆盖。
- 黄色菱形意味着代码已被部分覆盖 , 一些未经测试的分支。
- 红色菱形表示测试期间没有使用任何分支。
如何排除不需要的路径?
日常的项目我们测试覆盖率,通常是有范围的,比如一些配置文件等,我们是不需要测试的。为了避免此类不相关的类影响代码覆盖率,我们可以使用Jacoco插件将其排除。这里以启动类为例
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>cn/mycode/chen/myunit/MyUnitApplication.class</exclude>
</excludes>
</configuration>
...
</plugin>
运行结果可以看到只包含一个启动类文件的 cn/mycode/chen/myunit 路径已经不见了
设置覆盖率目标并验证
假设我们使用 CI/CD 来部署代码,我们想验证已经完成了多少行代码覆盖率或代码覆盖率百分比等。为此,我们需要在Jacoco 插件配置,在此执行中,我们添加了一条规则。规则是,对于 PACKAGE,计数应为 LINE,并且 LINE 覆盖率最小应为XX%。转到 Maven,选择 clean 和 verify 命令,然后选择 Run Maven Build 进行检查。
这里为了方便展示,已经将其他路径排除,只剩下service
<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>50%</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
测试一:
规则配置,配置覆盖率最小应为50%,执行maven的clean 和 verify 命令,检测结果失败
测试二:
规则配置,配置覆盖率最小应为20%,执行maven的clean 和 verify 命令,检测结果成功
JACOCO的不足
尽管JACOCO是一个功能强大的Java代码覆盖率工具,但仍存在一些不足之处,包括:
1、 配置和使用复杂
配置和使用JACOCO可能需要一些复杂的配置步骤,特别是对于初学者来说。一些开发人员可能需要花费一些时间来了解和掌握如何正确配置和使用JACOCO。
2、对动态代码的支持有限
JACOCO在对动态生成的代码或使用动态代理的代码的覆盖率分析方面支持有限。这可能导致在一些特殊场景下无法准确测量代码覆盖率。
3、 无法跟踪部分覆盖代码
在某些情况下,JACOCO可能无法覆盖到一些特殊情况下的代码,导致无法准确测量覆盖率。这可能会对测试结果产生一定的误导。
4、缺乏对其他语言的支持
目前JACOCO主要支持Java语言,对于其他编程语言的支持有限。这可能限制了JACOCO在多语言项目中的应用。
5、对于大型项目的性能影响
对于大型项目,JACOCO的性能可能会受到一定影响。在收集覆盖率数据时,可能会导致一些额外的开销,特别是在执行大量测试用例的情况下。
虽然JACOCO有一些不足之处,但它仍然是一个广泛使用的代码覆盖率工具,并且在许多项目中发挥了重要作用。对于使用JACOCO的开发人员来说,了解这些不足并采取相应的措施来解决或规避这些问题是很重要的。
JACOCO改进版super-Jacoco
Super-Jacoco(滴滴开源项目)
代码覆盖率的知识扩展
代码覆盖率,是一种通过计算测试过程中被执行的源代码占全部代码的比例,进而间接度量软件质量的过程。它在保证测试质量的时候潜在保证实际产品的质量。可以基于此在程序中寻找到没有被测试用例测试过的地方,进一步创建新的测试用用例来增加覆盖率。按性质,它属于白盒测试的范畴,即主要依据源代码的内部结构来设计测试用例,通过设计不同的输入来测试软件的不同部分。
代码覆盖率通常分为四种:
-
语句覆盖率(Statement Coverage)
衡量测试用例执行过程中覆盖到的代码语句比例。计算方法是统计被执行的代码语句数量与总代码语句数量的比例。 -
分支覆盖率(Branch Coverage)
衡量测试用例执行过程中覆盖到的代码分支比例。计算方法是统计被执行的代码分支数量与总代码分支数量的比例。 -
条件覆盖率(Condition Coverage)
衡量测试用例执行过程中覆盖到的条件语句比例。计算方法是统计被执行的条件语句数量与总条件语句数量的比例。 -
路径覆盖率(Path Coverage)
衡量测试用例执行过程中覆盖到的代码路径比例。计算方法是统计被执行的代码路径数量与总代码路径数量的比例。 -
函数覆盖率(Function Coverage)
衡量测试用例执行过程中覆盖到的函数或方法比例。计算方法是统计被执行的函数或方法数量与总函数或方法数量的比例。 -
边界值覆盖率(Boundary Value Coverage)
衡量测试用例执行过程中覆盖到的边界值情况比例。计算方法是统计覆盖到的边界值测试用例数量与总边界值测试用例数量的比例。 -
错误处理覆盖率(Error Handling Coverage)
衡量测试用例执行过程中覆盖到的错误处理情况比例。计算方法是统计覆盖到的错误处理测试用例数量与总错误处理测试用例数量的比例。