聊 一聊 maven 测试相关的插件

1,863 阅读5分钟

在之前的 聊一聊 maven 生命周期和 maven 插件编写 这篇文章中,简单聊了点maven 构建生命周期和如何编写一个 maven 插件。本篇文章从插件入手,来探讨下 maven 中那些于测试相关的插件,这些插件与工程师日常开发是密切相关的,可能很多情况下你不需要关注,因为已经有前辈帮你搞完了;“事不关己高高挂起” 与 “知其然知其所以然” 是两种不同的态度,对待技术,我建议是后者!

maven-surefire-plugin

在 Maven 项目中,用户基于 JUnit 或 TestNG 编写好了测试代码,这部分是工程师 coding 必须要要做好的;本地可以使用 idea 带的工具进行执行;倒是如果需要在 ci 中执行并且产出测试报告,idea 就帮不上什么忙了;此时,就需要依赖 maven 插件来帮助解决。执行测试代码,需要靠 maven-surefire-plugin 插件来实现。

一般情况下,工程师不需要显示配置 maven-surefire-plugin 插件,它是 mvn test 默认依赖使用的。

为什么用例没有执行

看下面这张图,使用的 junit 版本是 4.13.2

image.png

一个非常简单的 demo,demo 中只有一个单元测试用例,当使用 mvn test 执行时发现:

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

我去翻了一下插件的 使用介绍,看到了下面这段说明:

If nothing is configured, Surefire detects which JUnit version to use by the
following algorithm:

1. if the JUnit 5 Platform Engine is present in the project
    use junit-platform
2. if the JUnit version in the project >= 4.7 and the <<<parallel>>> configuration parameter has ANY value
    use junit47 provider
3. if JUnit >= 4.0 is present
    use junit4 provider
4. else
    use junit3.8.1

图中可以看到 maven-surefire-plugin 版本是 2.22.2,demo 中所使用的 junit 版本是 4.13.2,属于第二种算法:use junit47 provider,就是说如果是 JUnit 4.7 及以上版本,可以明确 声明一下:

目前已经提供的 provider 有 surefire-junit3, surefire-junit4, surefire-junit47 以及 surefire-testng

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
            <dependencies>
                <dependency>
                    <groupId>org.apache.maven.surefire</groupId>
                    <artifactId>surefire-junit47</artifactId>
                    <version>2.22.2</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

重新执行 mvn test 发现确实可以了。

image.png

那既然是基于版本去匹配的,那么换个思路,如果不通过配置来明确 junit 版本,是不是也可以通过另外一种降低 maven-surefire-plugin 来匹配;事实证明猎奇心理是有意思的,当把版本降到 2.21.0 时,发现用例也能正常跑。

image.png

跳过用例

默认情况下,surefire 插件会自动包含所有具有以下通配符模式的测试类:

  • "**/Test*.java"- 包括其所有子目录和所有以“Test”开头的 Java 文件名。
  • "**/*Test.java"- 包括其所有子目录和所有以“Test”结尾的 Java 文件名。
  • "**/*Tests.java"- 包括其所有子目录和所有以“Tests”结尾的 Java 文件名。
  • "**/*TestCase.java"- 包括其所有子目录和所有以“TestCase”结尾的 Java 文件名。

如果测试类不遵循默认通配符模式,则需要通过配置 Surefire 插件覆盖它们并指定要包含(或排除)的测试,否则可能扫不到,如下面这个就没有被执行到。

image.png

然后通过指定规则来匹配

image.png

同理,也可以通过 excludes 来排除不需要执行的用例

image.png

使用 mvn 指令来执行单个用例

大多数情况下,工程师习惯于面向 idea 来执行单个用例,这种方式是非常便捷的;当然同样也可以使用 mvn 命令来指定单个用例执行,以上面的例子来看,执行 Diff 这个用例可以这样:

 mvn test -Dtest=Diff

-Dtest 表示当前测试方法所在的测试类,当然也支持通配符 *

jacoco-maven-plugin

执行用例之后一般需要产生测试报告,目前 jacoco 是最流行的。可以通过如下方式在 pom 中声明:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.2</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <!-- attached to Maven test phase -->
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

重新执行 mvn test 可以看到 jacoco 执行的日志

[INFO] --- jacoco-maven-plugin:0.8.2:report (report) @ maven-plugin-guides ---
[INFO] Loading execution data file /Users/xxx/Documents/projects/github/gl-guides/maven-plugin-guides/target/jacoco.exec
[INFO] Analyzed bundle 'maven-plugin-guides' with 2 classes
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] gl-guides 0.0.1-SNAPSHOT ........................... SUCCESS [  0.172 s]
[INFO] maven-plugin-guides 0.0.1-SNAPSHOT ................. SUCCESS [  3.151 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

此时会在 target/site 目录下产生数据报告(ps: 这个默认路径是可以修改的)

image.png 打开 index.html 有详细的测试报告描述,大致如下:

  • 1、测试报告概览 image.png

  • 2、包概览 image.png

  • 3、类概览 image.png

对于某个核心的逻辑,如果期望这些代码的覆盖率必须满足一定的指标,也是可以通过 jacoco 来配置和设定的;比如我的测试类 PrepareTestInstance

public class PrepareTestInstance {
    public int add(int a, int b) {
        if (a < 0 || b < 0) {
            throw new IllegalArgumentException();
        }
        return a + b;
    }
}

覆盖率必须达到80%,可以这样配置,增加插件的 execution

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

然后通过 mvn verify 来执行 check,如果覆盖率不满足,则会得到如下的报错:

[INFO] --- jacoco-maven-plugin:0.8.2:check (jacoco-check) @ maven-plugin-guides ---
[INFO] Loading execution data file /Users/xxx/Documents/projects/github/gl-guides/maven-plugin-guides/target/jacoco.exec
[INFO] Analyzed bundle 'maven-plugin-guides' with 2 classes
[WARNING] Rule violated for package com.gl.guides.mvn: lines covered ratio is 0.4, but expected minimum is 0.8

总结

本文主要对 maven 的测试执行和测试报告产生对应的两个插件进行了介绍,希望通过本文,读者可以对这块有个基本的认识,以便于在日常的开发工作中,能够应对类似的问题和场景。

如果本篇文章对你有帮助,请不要吝啬点赞评论哦~,读者的认可才是持续输出的动力所在...

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿