jacoco使用示例与常用配置说明

基本概念

有时候,对于一些重要的项目或者重点类,我们希望重点测试,但是我们怎么评估测试质量呢?

这个时候,或许就需要jacoco了。

接下来,我们就来了解一下jacoco的基本概念与使用。

以及在某些条件不允许的情况下,我们如何跳过某些类,再结合mvn参数,让我们的单元测试报告看起来不那么乱。

jacoco会分析:指令(C0)、分支(C1)、行、方法、类型和循环复杂度的覆盖率

  1. 指令(Instructions,C0覆盖率,Java字节代码指令)
  2. 分支(Branches,C1覆盖率,分支覆盖率)
  3. 循环复杂度(Cyclomatic Complexity,cxty)
  4. 行(line)
  5. 方法(method)
  6. 类(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目录下。

结果如下:

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参数:

  1. element:范围,bundle、package、class、sourcefile、method
  2. includes:需要检查的元素集合名
  3. excludes:不需要被检查的元素
  4. imits:用于检查的limits

limit参数:

  1. counter:INSTRUCTION(指令)、LINE(行)、BRANCH(分支)、COMPLEXITY(复杂度)、METHOD(方法)、CLASS(类)
  2. value:TOTALCOUNT(总数量)、MISSEDCOUNT(未覆盖数量)、COVEREDCOUNT(覆盖数量)、MISSEDRATIO(未覆盖率)、COVEREDRATIO(覆盖率)
  3. minimum:最小值
  4. 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点非常重要:

  1. 首先要通过dependency把需要统计覆盖率的项目依赖引入
  2. 单独配置jacoco-maven-plugin,因为需要report-aggregate

示例项目下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值