JUnit5教程(4): JUnit5假设、测试套件和条件测试

你好啊,我是大阳。

这是专栏《SpringBoot自动化单元测试教程》的第四篇文章。本文我们将讨论JUnit5的假设、测试套件和条件测试。

1. JUnit5 假设

JUnit 5假设类提供静态方法来支持基于假设的条件测试执行。假设失败会导致测试中止。

当继续执行给定的测试方法没有意义时,通常使用假设。在测试报告中,这些测试将被标记为通过。

JUnit Assumptions(假设)类有以下方法:

  • Assumptions.assumeTrue()
  • Assumptions.assumeFalse()
  • Assumptions.assumingThat()

1.1 Assumptions.assumeTrue()

该方法验证给定假设为,如果假设为,则测试继续进行,否则,测试执行将中止。

它具有以下重载方法:

public static void assumeTrue(boolean assumption) throws TestAbortedException
public static void assumeTrue(boolean assumption, Supplier<String> messageSupplier) throws TestAbortedException
public static void assumeTrue(boolean assumption, String message) throws TestAbortedException

public static void assumeTrue(BooleanSupplier assumptionSupplier) throws TestAbortedException
public static void assumeTrue(BooleanSupplier assumptionSupplier, String message) throws TestAbortedException
public static void assumeTrue(BooleanSupplier assumptionSupplier, Supplier<String> messageSupplier) throws TestAbortedException

示例:

package cn.dayangshuo.junit5.tests;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
/**
 * @author DAYANG
 */
public class AssumeTests {
    @Test
    void testOnDev() {
        System.setProperty("ENV", "DEV");
        Assumptions.assumeTrue("DEV".equals(System.getProperty("ENV")));
        System.out.println("测试继续执行...");
    }
    /**
     * 测试失败,打印出失败消息
     */
    @Test
    void testOnProd() {
        System.setProperty("ENV", "PROD");
        Assumptions.assumeTrue("DEV".equals(System.getProperty("ENV")), AssumeTests::message);
        System.out.println("测试不会继续执行,不会打印此行...");
    }
    private static String message() {
        return "测试失败...";
    }
}

1.2 Assumptions.assumeFalse()

该方法验证给定假设为,如果假设为,则测试继续,否则,测试执行被中止。

它具有以下重载方法:

public static void assumeFalse(boolean assumption) throws TestAbortedException
public static void assumeFalse(boolean assumption, Supplier<String> messageSupplier) throws TestAbortedException
public static void assumeFalse(boolean assumption, String message) throws TestAbortedException

public static void assumeFalse(BooleanSupplier assumptionSupplier) throws TestAbortedException
public static void assumeFalse(BooleanSupplier assumptionSupplier, String message) throws TestAbortedException
public static void assumeFalse(BooleanSupplier assumptionSupplier, Supplier<String> messageSupplier) throws TestAbortedException

示例:

package cn.dayangshuo.junit5.tests;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Test;
/**
 * @author DAYANG
 */
public class AssumeTests {
    @Test
    void testOnDev() {
        System.setProperty("ENV", "DEV");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")), AssumeTests::message);
        System.out.println("测试不会继续执行,不会打印此行...");
    }
    /**
     * 测试失败,打印出失败消息
     */
    @Test
    void testOnProd() {
        System.setProperty("ENV", "PROD");
        Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV")));
        System.out.println("测试继续执行...");
    }
    private static String message() {
        return "测试失败...";
    }
}

1.3 Assertions.assumingThat()

该方法执行提供的可执行文件,但前提是提供的假设有效。与其他假设方法不同,此方法不会中止测试。

如果该假设无效,则该方法不起任何作用。如果假设有效且可执行文件抛出异常,则它将被视为常规测试失败。抛出的异常将按原样重新抛出,但被掩盖为未经检查的异常。

它有以下重载方法:

public static void assumingThat(boolean assumption, Executable executable)
public static void assumingThat(BooleanSupplier assumptionSupplier, Executable executable)

示例:

@Test
    void testInAllEnvironments() {
        System.setProperty("ENV", "DEV");
        Assumptions.assumingThat("DEV".equals(System.getProperty("ENV")),
                () -> {
                    //仅在DEV服务器上执行这些断言和打印
                    //即System.setProperty("ENV", "DEV")才会执行
                    Assertions.assertEquals(3, Calculator.add(4, 2));
                });

        // 在所有环境中执行这些断言
        Assertions.assertEquals(13, Calculator.add(6, 7));
    }

2. JUnit5测试套件

测试套件其实就是JUnit5允许我们运行多个包或者类中的测试方法,也就是分组测试。JUnit5中使用@Suite注解来声明测试套件。

在开始分组测试之前,我们先了解几个注解:

  • @Tag:测试类和方法可以通过此注解进行标记。这些标签以后可用于过滤测试发现和执行。
  • @Disabled:整个测试类或单个测试方法可以通过此注解禁止测试。

我们直接来看分组测试的代码示例:

package cn.dayangshuo.junit5;
import cn.dayangshuo.junit5.assertt.AssertTest;
import cn.dayangshuo.junit5.tests.LifeCycleTests;
import org.junit.platform.suite.api.*;
/**
 * @author DAYANG
 */
//将LifeCycleTests和AssertTest这两个类合并在一个分组中进行测试
@SelectClasses({LifeCycleTests.class, AssertTest.class})
//也可以直接将多个包合并一个组中测试
//@SelectPackages({"cn.dayangshuo.junit5.tests"})
//这个注解代表只测试含有DEV标签的测试类或者方法
//@IncludeTags("DEV")
@Suite
@SuiteDisplayName("测试套件,分组测试")
public class SuiteTests {
}

其中LifeCycleTests和AssertTest的代码如下,直接运行SuiteTests类,下面我们来看一下LifeCycleTests和AssertTest类中哪些方法会被执行:

package cn.dayangshuo.junit5.tests;

import cn.dayangshuo.junit5.Calculator;
import org.junit.jupiter.api.*;

/**
 * @author DAYANG
 */
public class LifeCycleTests {
    //执行了
    @Tag("DEV")
    @DisplayName("生命周期测试")
    @Test
    void testCalcOne() {
        System.out.println("======测试1执行了=======");
        Assertions.assertEquals(4, Calculator.add(2, 2));
    }
    //执行了,但是如果SuiteTests类有@IncludeTags("DEV")注解则不会执行
    @Tag("PROD")
    @Test
    void testCalcThree() {
        System.out.println("======测试3执行了=======");
        Assertions.assertEquals(6, Calculator.add(2, 4));
    }
    //不会执行,因为被禁用了
    @Disabled
    @Test
    void testCalcTwo() {
        System.out.println("======测试2执行了=======");
        Assertions.assertEquals(6, Calculator.add(2, 4));
    }
}

package cn.dayangshuo.junit5.assertt;
import cn.dayangshuo.junit5.Calculator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

import java.util.function.Supplier;

/**
 * @author DAYANG
 */
public class AssertTest {
    //执行了
    @Test
    @Tag("DEV")
    void assertTest() {
        //测试通过
        Assertions.assertNotEquals(3, Calculator.add(2, 2));
        //测试失败
        Assertions.assertNotEquals(4, Calculator.add(2, 2), "Calculator.add(2, 2) test failed");
        //测试失败
        Supplier<String> messageSupplier  = () -> "Calculator.add(2, 2) test failed";
        Assertions.assertNotEquals(4, Calculator.add(2, 2), messageSupplier);
    }
}

执行结果如图:

suite_result.png

套件测试中更多注解如下,可以使用他们包含或者排除某些类,某些包或者某些标签:

  • @SelectClasses
  • @SelectPackages
  • @IncludePackages
  • @ExcludePackages
  • @IncludeClassNamePatterns
  • @ExcludeClassNamePatterns
  • @IncludeTags
  • @ExcludeTags

3. 条件测试

JUnit Jupiter 中的ExecutionCondition扩展 API 允许开发人员以编程方式基于特定条件启用禁用容器或测试。这种条件的最简单示例是支持注释 的内置函数 。

如操作系统条件测试:@EnabledOnOs可以通过和@DisabledOnOs注释在特定操作系统上启用或禁用容器或测试 。

package cn.dayangshuo.junit5.tests;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author DAYANG
 */
public class ConditionsTests {

    @Test
    @EnabledOnOs(OS.MAC)
    void onlyOnMacOs() {
        // ...
    }

    @TestOnMac
    void testOnMac() {
        // ...
    }

    @Test
    @EnabledOnOs({ OS.LINUX, OS.MAC })
    void onLinuxOrMac() {
        // ...
    }

    @Test
    @DisabledOnOs(OS.WINDOWS)
    void notOnWindows() {
        // ...
    }

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Test
    @EnabledOnOs(OS.MAC)
    @interface TestOnMac {
    }
}

下一篇我们将讨论JUnit5让单元测试更便利的参数化测试,并且基于参数化测试我们可以更加灵活的配置我们的参数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容