条件测试

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. 使用Tomcat插件控制台中文乱码解决方案(IDEA)(Day_51)

    解决方案 1. File -> Settings... 2. 搜索 Runner (运行程序),在 'VM options:' 中添加:-Dfile.encoding=GB2312 注:GB23 ...

  2. springboot项目部署docker服务器提供api

    1.先将springboot项目打包,我这里用的是IDEA工具打包,打包完成后的jar包在 项目目录/target 中 2.打包完成后进入服务器器终端,将jar包上传到自己设置的目录中,这个目录需要跟 ...

  3. 深度树匹配模型(TDM)

    深度树匹配模型(TDM) 算法介绍 Tree-based Deep Match(TDM)是由阿里妈妈精准定向广告算法团队自主研发,基于深度学习上的大规模(千万级+)推荐系统算法框架.在大规模推荐系统的 ...

  4. 黎曼曲面Riemann Surface

    黎曼曲面Riemann Surface A Riemann surface is a surface-like configuration that covers the complex plane  ...

  5. 孟老板 BaseAdapter封装(四) PageHelper

    BaseAdapter封装(一) 简单封装 BaseAdapter封装(二) Header,footer BaseAdapter封装(三) 空数据占位图 BaseAdapter封装(四) PageHe ...

  6. java后端知识点梳理——web安全

    跨域 当浏览器执行脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域. 这里的同源指访问的协议.域名.端口都相同. 同源策略是由 Netscape 提出的著名安全策略,是浏览器最核心.基 ...

  7. Samba 服务基础

    配置SMB共享,跨平台的共享,Windows与Linux的共享 • Samba 软件项目 用途:为客户机提供共享使用的文件夹 协议:SMB(TCP 139).CIFS(TCP 445) • 所需软件包 ...

  8. Linkerd 2.10(Step by Step)—使用 Kustomize 自定义 Linkerd 的配置

    Linkerd 2.10 系列 快速上手 Linkerd v2 Service Mesh(服务网格) 腾讯云 K8S 集群实战 Service Mesh-Linkerd2 & Traefik2 ...

  9. NX二次开发-将3X3矩阵修正为正交且长度为单位长度的矩阵

    函数:UF_MTX3_ortho_normalize() 函数说明:将矩阵修正为正交且xyz长度为单位长度的矩阵.下图中输入的矩阵为三条线段的端点,经过修正后,生成一个坐标系. 1 #include ...

  10. ConcurrentSkipListSet - 秒懂

    疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 面试必备 + 面试必备 [博客园总入口 ] 疯狂创客圈 经典图书 : <Sprin ...