条件测试

JUnit5支持条件注解,根据布尔值判断是否执行测试。

自定义条件

@EnabledIf@DisabledIf注解用来设置自定义条件,示例:

@Test
@EnabledIf("customCondition")
void enabled() {
// ...
} @Test
@DisabledIf("customCondition")
void disabled() {
// ...
} boolean customCondition() {
return true;
}

其中customCondition()方法用来返回布尔值,它可以接受一个ExtensionContext类型的参数。如果定义在测试类外部,那么需要是static方法。

内置条件

JUnit5的org.junit.jupiter.api.condition包中内置了一些条件注解。

操作系统条件

@EnabledOnOsDisabledOnOs,示例:

@Test
@EnabledOnOs(MAC)
void onlyOnMacOs() {
// ...
} @TestOnMac
void testOnMac() {
// ...
} @Test
@EnabledOnOs({ LINUX, MAC })
void onLinuxOrMac() {
// ...
} @Test
@DisabledOnOs(WINDOWS)
void notOnWindows() {
// ...
} @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Test
@EnabledOnOs(MAC)
@interface TestOnMac {
}

JRE条件

@EnabledOnJre@DisabledOnJre用于指定版本,@EnabledForJreRange@DisabledForJreRange用于指定版本范围,示例:

@Test
@EnabledOnJre(JAVA_8)
void onlyOnJava8() {
// ...
} @Test
@EnabledOnJre({ JAVA_9, JAVA_10 })
void onJava9Or10() {
// ...
} @Test
@EnabledForJreRange(min = JAVA_9, max = JAVA_11)
void fromJava9to11() {
// ...
} @Test
@EnabledForJreRange(min = JAVA_9)
void fromJava9toCurrentJavaFeatureNumber() {
// ...
} @Test
@EnabledForJreRange(max = JAVA_11)
void fromJava8To11() {
// ...
} @Test
@DisabledOnJre(JAVA_9)
void notOnJava9() {
// ...
} @Test
@DisabledForJreRange(min = JAVA_9, max = JAVA_11)
void notFromJava9to11() {
// ...
} @Test
@DisabledForJreRange(min = JAVA_9)
void notFromJava9toCurrentJavaFeatureNumber() {
// ...
} @Test
@DisabledForJreRange(max = JAVA_11)
void notFromJava8to11() {
// ...
}

JVM系统属性条件

@EnabledIfSystemProperty@DisabledIfSystemProperty,示例:

@Test
@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")
void onlyOn64BitArchitectures() {
// ...
} @Test
@DisabledIfSystemProperty(named = "ci-server", matches = "true")
void notOnCiServer() {
// ...
}

环境变量条件

@EnabledIfEnvironmentVariable@DisabledIfEnvironmentVariable,示例:

@Test
@EnabledIfEnvironmentVariable(named = "ENV", matches = "staging-server")
void onlyOnStagingServer() {
// ...
} @Test
@DisabledIfEnvironmentVariable(named = "ENV", matches = ".*development.*")
void notOnDeveloperWorkstation() {
// ...
}

嵌套测试

嵌套测试可以帮助我们对测试结构进行分层。借助于Java嵌套类的语法,JUnit5可以通过@Nested注解,实现嵌套测试,示例:

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.EmptyStackException;
import java.util.Stack; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; @DisplayName("A stack")
class TestingAStackDemo { Stack<Object> stack; @Test
@DisplayName("is instantiated with new Stack()")
void isInstantiatedWithNew() {
new Stack<>();
} @Nested
@DisplayName("when new")
class WhenNew { @BeforeEach
void createNewStack() {
stack = new Stack<>();
} @Test
@DisplayName("is empty")
void isEmpty() {
assertTrue(stack.isEmpty());
} @Test
@DisplayName("throws EmptyStackException when popped")
void throwsExceptionWhenPopped() {
assertThrows(EmptyStackException.class, stack::pop);
} @Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
assertThrows(EmptyStackException.class, stack::peek);
} @Nested
@DisplayName("after pushing an element")
class AfterPushing { String anElement = "an element"; @BeforeEach
void pushAnElement() {
stack.push(anElement);
} @Test
@DisplayName("it is no longer empty")
void isNotEmpty() {
assertFalse(stack.isEmpty());
} @Test
@DisplayName("returns the element when popped and is empty")
void returnElementWhenPopped() {
assertEquals(anElement, stack.pop());
assertTrue(stack.isEmpty());
} @Test
@DisplayName("returns the element when peeked but remains not empty")
void returnElementWhenPeeked() {
assertEquals(anElement, stack.peek());
assertFalse(stack.isEmpty());
}
}
}
}

外部测试类通过@BeforeEach向内部测试类传递变量。

执行后结果:

重复测试

@RepeatedTest注解能控制测试方法的重复执行次数,示例:

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.logging.Logger;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import org.junit.jupiter.api.TestInfo; class RepeatedTestsDemo { private Logger logger = // ... @BeforeEach
void beforeEach(TestInfo testInfo, RepetitionInfo repetitionInfo) {
int currentRepetition = repetitionInfo.getCurrentRepetition();
int totalRepetitions = repetitionInfo.getTotalRepetitions();
String methodName = testInfo.getTestMethod().get().getName();
logger.info(String.format("About to execute repetition %d of %d for %s", //
currentRepetition, totalRepetitions, methodName));
} @RepeatedTest(10)
void repeatedTest() {
// ...
} @RepeatedTest(5)
void repeatedTestWithRepetitionInfo(RepetitionInfo repetitionInfo) {
assertEquals(5, repetitionInfo.getTotalRepetitions());
} @RepeatedTest(value = 1, name = "{displayName} {currentRepetition}/{totalRepetitions}")
@DisplayName("Repeat!")
void customDisplayName(TestInfo testInfo) {
assertEquals("Repeat! 1/1", testInfo.getDisplayName());
} @RepeatedTest(value = 1, name = RepeatedTest.LONG_DISPLAY_NAME)
@DisplayName("Details...")
void customDisplayNameWithLongPattern(TestInfo testInfo) {
assertEquals("Details... :: repetition 1 of 1", testInfo.getDisplayName());
} @RepeatedTest(value = 5, name = "Wiederholung {currentRepetition} von {totalRepetitions}")
void repeatedTestInGerman() {
// ...
} }

其中name可以用来自定义重复测试的显示名字,{currentRepetition}{totalRepetitions}是当前次数和总共次数的变量。

执行结果:

├─ RepeatedTestsDemo
│ ├─ repeatedTest()
│ │ ├─ repetition 1 of 10
│ │ ├─ repetition 2 of 10
│ │ ├─ repetition 3 of 10
│ │ ├─ repetition 4 of 10
│ │ ├─ repetition 5 of 10
│ │ ├─ repetition 6 of 10
│ │ ├─ repetition 7 of 10
│ │ ├─ repetition 8 of 10
│ │ ├─ repetition 9 of 10
│ │ └─ repetition 10 of 10
│ ├─ repeatedTestWithRepetitionInfo(RepetitionInfo)
│ │ ├─ repetition 1 of 5
│ │ ├─ repetition 2 of 5
│ │ ├─ repetition 3 of 5
│ │ ├─ repetition 4 of 5
│ │ └─ repetition 5 of 5
│ ├─ Repeat!
│ │ └─ Repeat! 1/1
│ ├─ Details...
│ │ └─ Details... :: repetition 1 of 1
│ └─ repeatedTestInGerman()
│ ├─ Wiederholung 1 von 5
│ ├─ Wiederholung 2 von 5
│ ├─ Wiederholung 3 von 5
│ ├─ Wiederholung 4 von 5
│ └─ Wiederholung 5 von 5

小结

本文分别对JUnit5的条件测试、嵌套测试、重复测试进行了介绍,它们可以使得测试更加灵活和富有层次。除了这些,JUnit5还支持另一个重要且常见的测试:参数化测试。

参考资料:

https://junit.org/junit5/docs/current/user-guide/#writing-tests-conditional-execution

https://junit.org/junit5/docs/current/user-guide/#writing-tests-nested

https://junit.org/junit5/docs/current/user-guide/#writing-tests-repeated-tests

JUnit5的条件测试、嵌套测试、重复测试的更多相关文章

  1. 如何避免测试人员提交重复的Bug

    我们在软件测试过程中,由于不同人员测试同一个项目,所以往往会出现Bug重复提交情况,导致对整个项目和人员产生影响: 浪费测试人员时间和精力,从而影响测试进度 浪费开发人员重复看Bug时间 若开发人员由 ...

  2. junit测试延伸--方法的重复测试

    在实际编码测试中,我们有的时候需要对一个方法进行多次测试,那么怎么办呢?这个问题和测试套件解决的方案一样,我们总不能不停的去右键run as,那怎么办呢?还好伟大的junit帮我们想到了. OK,现在 ...

  3. LTP--linux稳定性测试 linux性能测试 ltp压力测试 内核更新 稳定性测试

    LTP--linux稳定性测试 linux性能测试 ltp压力测试 zhangzj1030关注14人评论33721人阅读2011-12-09 12:07:45   说明:在写这篇文章之前,本人也不曾了 ...

  4. 组合测试(Combinatorial Test)/配对测试 (pairwise)

    组合测试方法:配对测试实践 实施组合测试 常用的Pairwise工具集:http://www.pairwise.org/tools.asp 成对测试(Pairwise Testing)又称结对测试.两 ...

  5. Selenium & Webdriver 远程测试和多线程并发测试

    Selenium & Webdriver 远程测试和多线程并发测试 Selenium Webdriver自动化测试,初学者可以使用selenium ide录制脚本,然后生成java程序导入ec ...

  6. 【星云测试】开发者测试(2)-采用精准测试工具对J2EE Guns开发框架进行测试

    配置测试Guns Guns简介 Guns是一个近几年来基于SpringBoot的开源便利且较新的JavaEE项目开发框架,它整合了springmvc + shiro + mybatis-plus + ...

  7. 使用iozone测试磁盘性能(测试文件读写)

    IOzone是一个文件系统测试基准工具.可以测试不同的操作系统中文件系统的读写性能.可以通过 write, re-write, read, re-read, random read, random w ...

  8. web 压力测试工具ab压力测试详解

    Web性能压力测试工具之ApacheBench(ab)详解 原文:http://www.ha97.com/4617.html PS:网站性能压力测试是性能调优过程中必不可少的一环.只有让服务器处在高压 ...

  9. 【测试基础】App测试要点总结

    测试工作过程中思维过程:测试人员常被看作Bug寻找者,程序的破坏者. 1.好的测试工程师所具备的能力: 细心的观察能力 有效的提问能力 产品的业务能力 好奇心 2.测试人员需要询问问题:测试人员的核心 ...

随机推荐

  1. Python对比两个txt文件内容

    difflib模块作为python的标准库模块,无需安装,作用是比对文本之间的差异,且支持输出可读性比较强的html格式.#!coding=utf-8 # 2018-9-19 import sys i ...

  2. STM32F1移植UCOSII

    作者:珵旭媛 下载对应版本的UCOSII https://www.micrium.com/downloadcenter/,你会少修改很多东西: 下载下来后是这样的文件夹,并且Software里面的才是 ...

  3. grasshopper之python电池执行逻辑

    在grasshopper中,需要导入的包虽然不多,但是相当绕人,所要实现的操作往往找不到,暂时做个分类. 双击输入 python 电池: # 导入rhino 包 import Rhino #Rhino ...

  4. jquery 改变标签样式

    jQuery改变标签的样式一般有3种 预置好class,然后通过jQuery改变元素的class名,使用的是addClass.removeClass 直接改变元素的css属性值,这种是通过添加styl ...

  5. 视频教学动作修饰语:CVPR2020论文解析

    视频教学动作修饰语:CVPR2020论文解析 Action Modifiers: Learning from Adverbs in Instructional Videos 论文链接:https://a ...

  6. 白*衡(Color Constancy,无监督AWB):CVPR2019论文解析

    白*衡(Color Constancy,无监督AWB):CVPR2019论文解析 Quasi-Unsupervised Color Constancy 论文链接: http://openaccess. ...

  7. 智能物联网(AIoT,2020年)(下)

    智能物联网(AIoT,2020年)(下) 12工业物联网是AIoT在工业领域第一战场 工业物联网分为感知.决策.执行,OS与软件是大脑+神经 13工业场景下一步如何使用AIoT 不止工业物联网:用人工 ...

  8. RGB Color Codes Chart

    RGB Color Codes Chart RGB颜色空间 RGB颜色空间或RGB颜色系统,从红色.绿色和蓝色的组合中构造所有颜色. 红色.绿色和蓝色各使用8位,它们的整数值从0到255.这使得256 ...

  9. Linux学习笔记:Linux命令之权限管理命令

    权限管理命令 chmod(重要) 命令名称:chmod 英文原意:change the permissions mode of a file 执行权限:所有用户 功能描述:改变文件或目录权限 语法:c ...

  10. 狂神说JUC学习笔记(一)

    狂神说JUC的原版笔记: 链接:https://pan.baidu.com/s/12zrGI4JyZhmkQh0cqEO4BA 提取码:d65c 我的笔记在狂神的笔记上增加了一些知识点或者做了些许修改 ...