基本概念
有时候,对于一些重要的项目或者重点类,我们希望重点测试,但是我们怎么评估测试质量呢?
这个时候,或许就需要jacoco了。
接下来,我们就来了解一下jacoco的基本概念与使用。
以及在某些条件不允许的情况下,我们如何跳过某些类,再结合mvn参数,让我们的单元测试报告看起来不那么乱。
jacoco会分析:指令(C0)、分支(C1)、行、方法、类型和循环复杂度的覆盖率
- 指令(Instructions,C0覆盖率,Java字节代码指令)
- 分支(Branches,C1覆盖率,分支覆盖率)
- 循环复杂度(Cyclomatic Complexity,cxty)
- 行(line)
- 方法(method)
- 类(class)
jacoco结果显示:
分支:
- 无覆盖范围:该行没有分支执行(红色菱形)
- 部分覆盖:仅执行了该行中的一部分分支(黄色菱形)
- 全面覆盖:该行中的所有分支均已执行(绿色菱形)
行:
- 无覆盖:该行中没有指令被执行(红色背景)
- 部分覆盖:仅执行了该行中的一部分指令(黄色背景)
- 全面覆盖:该行中的所有指令均已执行(绿色背景)
如果上面内容比较抽象,可以看看下面具体实例。
基本使用
maven配置
对于maven项目可以参考下面的配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>vip.meet</groupId> <artifactId>jacoco-test</artifactId> <version>1.0.0</version> <name>jacoco-test</name> <description>单元测试报告</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-launcher</artifactId> <version>1.7.2</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>UTF8</encoding> </configuration> <version>3.8.1</version> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.11</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <includes> <!-- /SayHi --> </includes> <excludes> </excludes> </configuration> </execution> <execution> <id>generate-code-coverage-report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> <configuration> <formats>HTML</formats> <includes> <!-- /SayHi.class--> </includes> <excludes> <!-- /SayHello.class--> </excludes> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <skipTests>false</skipTests> <testFailureIgnore>true</testFailureIgnore> <forkMode>once</forkMode> </configuration> </plugin> </plugins> </build> </project>
讯享网
类与测试类
业务类:
讯享网public class SayHi {
public static String hi(String name) {
if (name == null) {
return "名字不能为空"; } else if (name.trim().isEmpty()) {
return "名字不能为空字符串"; } else {
return "Hi " + name; } } }
public class SayHello {
public static String hello(String name) {
if (name == null) {
return "名字不能为空"; } else if (name.trim().isEmpty()) {
return "名字不能为空字符串"; } else {
return "Hello " + name; } } }
测试类:
讯享网import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class SayHiTest {
@Test void getMessage() {
assertEquals("Hi allen", SayHi.hi("allen")); SayHi.hi(""); SayHi.hi(null); } }
import org.junit.jupiter.api.Test; class SayHelloTest {
@Test void hello() {
SayHello.hello("allen"); } }
执行mvn命令,执行单元测试:
讯享网mvn clean test
输出的目录默认在项目目录下的target/site/jacoco目录下。
结果如下:
其中1是指令覆盖率,2是分支覆盖率,后面是没有被覆盖到的复杂度(行、方法、类)与总复杂度(行、方法、类)
Total部分是汇总信息。

我们可以接着往下点,可以看到具体的类、方法、行的覆盖信息。
【具体方法行覆盖信息】

jacoco常用配置
prepare-agent
jacoco.exec在这个阶段生成。
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.11</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <classDumpDir>target/site/jacoco/med-class</classDumpDir> <excludes> <exclude>vip.meet.SayHello</exclude> </excludes> <includes> <include>vip.meet.SayHi</include> </includes> </configuration> </execution> </executions> </plugin>
report阶段
最常用的就是生成报告的时候,我们可能不想报告太乱,我们可以跳过某些类的,或者只为某些类生成报告。
讯享网<execution> <id>generate-code-coverage-report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> <configuration> <!--定义输出的文件夹--> <outputDirectory>target/jacoco</outputDirectory> <!--执行数据的文件--> <dataFile>${project.build.directory}/jacoco.exec</dataFile> <!--要从报告中排除的类文件列表,支持通配符(*和?)--> <excludes>/api//SayHello*.class</excludes> <!--包含生成报告的文件列表,支持通配符(*和?)--> <includes>/SayHi.class</includes> <!--HTML 报告页面中使用的页脚文本--> <footer></footer> <!--生成报告的文件类型,HTML(默认)、XML、CSV--> <formats>HTML</formats> <!--生成报告的编码格式,默认UTF-8--> <outputEncoding>UTF-8</outputEncoding> <!--跳过执行的标签--> <skip></skip> <!--源文件编码--> <sourceEncoding>UTF-8</sourceEncoding> <!--HTML报告的标题--> <title>${project.name}-单元测试报告</title> </configuration> </execution>
例如,我只想看SayHi的覆盖测试情况,就可以在report阶段配置includes为 /SayHi.class
rule-规则检查
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.11</version> <configuration> <rules> <rule implementation="org.jacoco.maven.RuleConfiguration"> <element>BUNDLE</element> <limits> <!-- 方法覆盖率最小值为80% --> <limit implementation="org.jacoco.report.check.Limit"> <counter>METHOD</counter> <value>COVEREDRATIO</value> <minimum>0.8</minimum> </limit> <!-- 分支覆盖最小值为50% --> <limit implementation="org.jacoco.report.check.Limit"> <counter>BRANCH</counter> <value>COVEREDRATIO</value> <minimum>0.5</minimum> </limit> <!-- 类必须全部被覆盖 --> <limit implementation="org.jacoco.report.check.Limit"> <counter>CLASS</counter> <value>MISSEDCOUNT</value> <maximum>0</maximum> </limit> </limits> </rule> </rules> </configuration> </plugin>
rule参数:
- element:范围,bundle、package、class、sourcefile、method
- includes:需要检查的元素集合名
- excludes:不需要被检查的元素
- imits:用于检查的limits
limit参数:
- counter:INSTRUCTION(指令)、LINE(行)、BRANCH(分支)、COMPLEXITY(复杂度)、METHOD(方法)、CLASS(类)
- value:TOTALCOUNT(总数量)、MISSEDCOUNT(未覆盖数量)、COVEREDCOUNT(覆盖数量)、MISSEDRATIO(未覆盖率)、COVEREDRATIO(覆盖率)
- minimum:最小值
- maximum:最大值
rule检查不满足条件的时候,mvn test阶段直接报错。
rule是在check阶段执行的
讯享网 <execution> <id>check</id> <goals> <goal>check</goal> </goals> </execution>
聚合项目配置

聚合项目可以单独添加一个子项目,来做聚合操作,只需配置:report-aggregate
<execution> <id>jacoco-report-aggregate</id> <phase>test</phase> <goals> <goal>report-aggregate</goal> </goals> </execution>
具体pom配置可以参考下面
父项目pom配置
讯享网<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>vip.meet</groupId> <artifactId>jacoco-aggregate-test</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <name>jacoco-test</name> <description>单元测试覆盖率集合报告</description> <modules> <module>jacoco-one</module> <module>jacoco-two</module> <module>jacoco-aggregate</module> </modules> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-launcher</artifactId> <version>1.7.2</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>UTF8</encoding> </configuration> <version>3.8.1</version> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.11</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> </configuration> </execution> <execution> <id>generate-code-coverage-report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> <configuration> <formats>HTML</formats> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <skipTests>false</skipTests> <testFailureIgnore>true</testFailureIgnore> <forkMode>once</forkMode> </configuration> </plugin> </plugins> </build> </project>
配置聚合项目jacoco-maven-plugin其实最好放到子项目,按需配置,这里为了直观直接配置到了父项目的pom中,就意味着所有的子项目都继承了jacoco-maven-plugin。
我们可以看到配置了3个子项目:
<modules> <module>jacoco-one</module> <module>jacoco-two</module> <module>jacoco-aggregate</module> </modules>
jacoco-one和jacoco-two是正常的子项目,jacoco-aggregate是用来做聚合报告的。
主要需要看一下jacoco-aggregate的pom配置:
讯享网<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>vip.meet</groupId> <artifactId>jacoco-aggregate-test</artifactId> <version>1.0.0</version> </parent> <artifactId>jacoco-aggregate</artifactId> <packaging>jar</packaging> <dependencies> <dependency> <groupId>vip.meet</groupId> <artifactId>jacoco-one</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>vip.meet</groupId> <artifactId>jacoco-two</artifactId> <version>1.0.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.11</version> <executions> <execution> <id>default-prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> </configuration> </execution> <execution> <id>default-report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> </execution> <execution> <id>jacoco-report-aggregate</id> <phase>test</phase> <goals> <goal>report-aggregate</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
2点非常重要:
- 首先要通过dependency把需要统计覆盖率的项目依赖引入
- 单独配置jacoco-maven-plugin,因为需要report-aggregate
示例项目下载

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/28086.html