Contents

Jacoco的简介

1. 概述

代码覆盖率一种软件指标 ,用于衡量在自动化测试期间执行了多少行代码。 在本教程中,我们将介绍使用JaCoCo( Java 项目的代码覆盖率报告生成器)的一些实际方面。

2.Maven配置

为了启动并运行 JaCoCo,我们需要在pom.xml文件中声明这个maven 插件:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.7.201606060606</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

此处提供的链接将始终转到 maven 中央存储库中插件的最新版本。

3. 代码覆盖率报告

在我们开始查看 JaCoCo 的代码覆盖能力之前,我们需要有一个代码示例。这是一个简单的 Java 函数,用于检查字符串是否向后和向前读取相同:

public boolean isPalindrome(String inputString) {
    if (inputString.length() == 0) {
        return true;
    } else {
        char firstChar = inputString.charAt(0);
        char lastChar = inputString.charAt(inputString.length() - 1);
        String mid = inputString.substring(1, inputString.length() - 1);
        return (firstChar == lastChar) && isPalindrome(mid);
    }
}

现在我们只需要一个简单的JUnit测试:

@Test
public void whenEmptyString_thenAccept() {
    Palindrome palindromeTester = new Palindrome();
    assertTrue(palindromeTester.isPalindrome(""));
}

使用 JUnit 运行测试将自动启动 JaCoCo 代理。它将在目标目录target/jacoco.exec中创建二进制格式的覆盖率报告。 显然我们不能单枪匹马地解释输出,但其他工具和插件可以,例如**Sonar Qube **。 好消息是我们可以使用jacoco:report 目标来生成多种格式的可读代码覆盖率报告,例如 HTML、CSV 和 XML。 例如,现在我们可以查看target/site/jacoco/index.html页面,看看生成的报告是什么样的:

/uploads/jacoco/1.png 在报告中提供的链接Palindrome.java之后,我们可以深入了解每个 Java 类的更详细视图:

/uploads/jacoco/2.png 请注意,由于EclEmma Eclipse 插件 ,我们可以在 Eclipse 中使用 JaCoCo 以零配置直接管理代码覆盖率。

4.报告分析

我们的报告显示了 21% 的指令覆盖率、17% 的分支覆盖率、3/5 的圈复杂度等等。 JaCoCo 在报告中显示的 38 条指令指的是**字节码指令,**而不是普通的 Java 代码指令。 JaCoCo 报告通过使用带有分支颜色的菱形和线条的背景颜色来帮助我们直观地分析代码覆盖率:

  • 红色菱形 表示在测试阶段没有执行任何分支。
  • 黄色菱形 表示代码被部分覆盖——一些分支没有被执行。
  • 绿色菱形表示测试期间所有分支都已被执行。

相同的颜色代码适用于背景颜色,但适用于线条覆盖。 JaCoCo 主要提供了三个重要的指标:

  • 行覆盖率根据测试调用的 Java 字节码指令的数量反映了已执行的代码量。
  • 分支覆盖率显示代码中执行分支的百分比,通常与if/elseswitch语句相关。
  • 圈复杂度通过线性组合给出覆盖代码中所有可能路径所需的路径数来反映代码的复杂性。

举个简单的例子,如果代码中没有ifswitch语句,则圈复杂度将为 1,因为我们只需要一个执行路径即可覆盖整个代码。 通常,圈复杂度反映了我们需要实现的测试用例的数量才能覆盖整个代码。

5. 概念分解

JaCoCo 作为**Java 代理运行。它负责在运行测试时检测字节码。**JaCoCo 深入研究每条指令,并显示在每次测试期间执行了哪些行。 为了收集覆盖率数据,JaCoCo 使用ASM 进行动态代码检测,在流程中从JVM 工具接口 接收事件:

/uploads/jacoco/3.png 也可以在服务器模式下运行 JaCoCo 代理。在这种情况下,我们可以使用jacoco:dump 作为目标来运行我们的测试,以启动转储请求。 我们可以关注官方文档链接 以获取有关 JaCoCo 设计的更多详细信息。

6. 代码覆盖率分数

现在我们对 JaCoCo 的工作原理有了一些了解,让我们提高代码覆盖率。 为了实现 100% 的代码覆盖率,我们需要引入测试来覆盖初始报告中显示的缺失部分:

@Test
public void whenPalindrom_thenAccept() {
    Palindrome palindromeTester = new Palindrome();
    assertTrue(palindromeTester.isPalindrome("noon"));
}
    
@Test
public void whenNearPalindrom_thanReject(){
    Palindrome palindromeTester = new Palindrome();
    assertFalse(palindromeTester.isPalindrome("neon"));
}

现在我们有足够的测试来覆盖我们的整个代码,但是为了确保这一点,让我们运行 Maven 命令mvn jacoco:report 来发布覆盖率报告:

/uploads/jacoco/4.png

正如我们所看到的,我们代码中的所有行/分支/路径都被完全覆盖:

/uploads/jacoco/5.png

在现实世界的项目中,随着开发的深入,我们需要跟踪代码覆盖率分数。 JaCoCo 提供了一种声明应满足的最低要求的简单方法,否则构建将失败。 我们可以通过在pom.xml文件中添加以下检查目标来做到这一点:

<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>0.50</minimum>
                    </limit>
                </limits>
            </rule>
        </rules>
    </configuration>
</execution>

正如我们所见,我们将线路覆盖率的最低分数限制为 50%。

jacoco :check目标绑定verify,因此我们可以运行 Maven 命令mvn clean verify来检查规则是否被遵守。日志将显示如下内容:

[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.7.7.201606060606:check 
  (jacoco-check) on project mutation-testing: Coverage checks have not been met.