junit5 入门系列教程-17-junit5 动态测试(DynamicTest)
目录
- 目录
- 动态测试
- 生命周期
- 测试案例
- 系列导航
动态测试
在标注中描述的JUnit Jupiter中的标准@Test注释与JUnit 4中的@Test注释非常相似。两者都描述了实现测试用例的方法。这些测试用例是静态的,因为它们是在编译时完全指定的,并且它们的行为不能被运行时发生的任何事情所改变。假设提供了一种基本的动态行为形式,但在其表达性上却被故意限制。
除了这些标准测试之外,JUnit Jupiter还引入了一种全新的测试编程模型。
这种新类型的测试是一种动态测试,它是由一个工厂方法在运行时生成的,该方法用@TestFactory注释。
与@Test方法相反,@TestFactory方法本身不是测试用例,而是测试用例的工厂。因此,动态测试是工厂的产品。从技术上讲,@TestFactory方法必须返回DynamicNode实例的流、集合、可迭代或迭代器。
DynamicNode的可实例化子类是DynamicContainer和DynamicTest。DynamicContainer实例由显示名和动态子节点列表组成,允许创建动态节点的任意嵌套层次结构。然后,动态测试实例将被延迟执行,从而支持动态甚至不确定的测试用例生成。
@TestFactory返回的任何流都将通过调用stream.close()来适当地关闭,从而使使用诸如fil. lines()之类的资源变得安全。
与@Test方法一样,@TestFactory方法不能是私有的或静态的,并且可以选择性地声明参数解析器解析的参数。
动态测试是在运行时生成的测试用例。它由显示名和可执行文件组成。可执行文件是一个@FunctionalInterface,这意味着动态测试的实现可以作为lambda表达式或方法引用提供。
生命周期
动态测试的执行生命周期与标准的@测试用例的执行生命周期完全不同。特别地,对于单个动态测试没有生命周期回调。
这意味着@BeforeEach和@AfterEach方法及其对应的扩展回调对于@TestFactory方法执行,而不是对每个动态测试执行。
换句话说,如果在动态测试的lambda表达式中访问测试实例中的字段,那么这些字段不会在执行由相同的@TestFactory方法生成的单个动态测试之间通过回调方法或扩展来重置。
从JUnit Jupiter 5.2.0开始,动态测试必须始终由工厂方法创建;然而,这可能会在稍后的版本中得到注册设施的补充。
注意
这是一个实验特性。
测试案例
下面的DynamicTestsDemo类演示了几个测试工厂和动态测试的例子。
第一个方法返回无效的返回类型。由于在编译时无法检测到无效的返回类型,所以在运行时检测到JUnitException时将抛出。
接下来的五个方法是非常简单的示例,它们演示了动态测试实例的集合、可迭代、迭代器或流的生成。这些示例中的大多数并没有真正显示动态行为,只是在原则上演示了受支持的返回类型。然而,dynamicTestsFromStream()和dynamicTestsFromIntStream()演示了为给定的一组字符串或一组输入数字生成动态测试是多么容易。
下一种方法实际上是动态的。generateRandomNumberOfTests()实现了一个迭代器,它生成随机数、一个显示名称生成器和一个测试执行器,然后提供所有3个到DynamicTest.stream()。尽管generateRandomNumberOfTests()的非确定性行为当然与测试可重复性存在冲突,因此应该谨慎使用,但它可以展示动态测试的表现力和威力。
最后一种方法使用DynamicContainer生成嵌套的动态测试层次结构。
- DynamicTestsDemo.java
import org.junit.jupiter.api.DynamicNode;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.function.ThrowingConsumer;import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.DynamicContainer.dynamicContainer;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;public class DynamicTestsDemo {// This will result in a JUnitException!@TestFactoryList<String> dynamicTestsWithInvalidReturnType() {return Arrays.asList("Hello");}@TestFactoryCollection<DynamicTest> dynamicTestsFromCollection() {return Arrays.asList(dynamicTest("1st dynamic test", () -> assertTrue(true)),dynamicTest("2nd dynamic test", () -> assertEquals(4, 2 * 2)));}@TestFactoryIterable<DynamicTest> dynamicTestsFromIterable() {return Arrays.asList(dynamicTest("3rd dynamic test", () -> assertTrue(true)),dynamicTest("4th dynamic test", () -> assertEquals(4, 2 * 2)));}@TestFactoryIterator<DynamicTest> dynamicTestsFromIterator() {return Arrays.asList(dynamicTest("5th dynamic test", () -> assertTrue(true)),dynamicTest("6th dynamic test", () -> assertEquals(4, 2 * 2))).iterator();}@TestFactoryStream<DynamicTest> dynamicTestsFromStream() {return Stream.of("A", "B", "C").map(str -> dynamicTest("test" + str, () -> { /* ... */ }));}@TestFactoryStream<DynamicTest> dynamicTestsFromIntStream() {// Generates tests for the first 10 even integers.return IntStream.iterate(0, n -> n + 2).limit(10).mapToObj(n -> dynamicTest("test" + n, () -> assertTrue(n % 2 == 0)));}@TestFactoryStream<DynamicTest> generateRandomNumberOfTests() {// Generates random positive integers between 0 and 100 until// a number evenly divisible by 7 is encountered.Iterator<Integer> inputGenerator = new Iterator<Integer>() {Random random = new Random();int current;@Overridepublic boolean hasNext() {current = random.nextInt(100);return current % 7 != 0;}@Overridepublic Integer next() {return current;}};// Generates display names like: input:5, input:37, input:85, etc.Function<Integer, String> displayNameGenerator = (input) -> "input:" + input;// Executes tests based on the current input value.ThrowingConsumer<Integer> testExecutor = (input) -> assertTrue(input % 7 != 0);// Returns a stream of dynamic tests.return DynamicTest.stream(inputGenerator, displayNameGenerator, testExecutor);}@TestFactoryStream<DynamicNode> dynamicTestsWithContainers() {return Stream.of("A", "B", "C").map(input -> dynamicContainer("Container " + input, Stream.of(dynamicTest("not null", () -> assertNotNull(input)),dynamicContainer("properties", Stream.of(dynamicTest("length > 0", () -> assertTrue(input.length() > 0)),dynamicTest("not empty", () -> assertFalse(input.isEmpty())))))));}
}
系列导航
系列导航
junit5 入门系列教程-17-junit5 动态测试(DynamicTest)相关推荐
- junit5 入门系列教程-02-junit5 注解详解
目录 目录 Junit5 注解 @Test @ParameterizedTest @RepeatedTest @TestFactory @TestInstance @TestTemplate @Dis ...
- Provisioning Services 7.8 入门系列教程之十四 UEFI支持和BOOTPTAB 编辑器
续Provisioning Services 7.8 入门系列教程之十三 使用 Boot Device Management(BDM) UEFI,全称Unified Extensible Firmw ...
- Provisioning Services 7.8 入门系列教程之十三 使用 Boot Device Management(BDM)
续Provisioning Services 7.8 入门系列教程之十二 实现高可用性 可以使用 Boot Device Management 实用程序将 IP 和引导信息(引导设备)交付给目标设备, ...
- STM32 基础系列教程 17 – CRC
前言 学习stm32 循环冗余校验(CRC)计算单元接口使用,学会stm32f103 CRC应用与编程,关于CRC的基础知识请各位自行百度,STM32有些芯片的CRC多项式可自由设定,有些则是固定值0 ...
- graphviz 画决策树_数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris
数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris 加载数据集 数据特征 训练 随机森林 调参工程师 结尾 数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iri ...
- Provisioning Services 7.8 入门系列教程之十一 通过版本控制自动更新虚拟磁盘
续Provisioning Services 7.8 入门系列教程之十 通过类自动更新虚拟磁盘 从前两的两种更新方式可以看出,它们有一个共同的特点,即需要产生(复制)完成的虚拟磁盘副本,然后进行相关的 ...
- html5游戏制作入门系列教程(八)
今天,我已经准备了一个新的游戏 – SkyWalker.基本上 – 这是用飞飞行模拟射击类游戏.我们的目标到达终点线.这个游戏还有其它一些特点,例如使用飞机运动动画和爆炸动画,多按键处理(例如同时移动 ...
- html5游戏制作入门系列教程(七)
我们继续这一系列文章,使用HTML5的canvas组件进行游戏开发.我们将要更新完善我们的第4课html5游戏制作入门系列教程(四)的游戏实例,并增加了火球,敌人和碰撞检测等功能模块.所以,现在我们的 ...
- html5游戏制作入门系列教程(六)
我们继续这一系列文章,使用HTML5的canvas组件进行游戏开发.今天,我们将创建我们的第一个完整的游戏 – 打砖块.在这一课中,我会告诉你如何检测基本的碰撞和HTML5的本地存储.您可以使用鼠标和 ...
最新文章
- 并发编程线程通信之管道流
- html左边动右边不动,网页布局//上左不动,其他滑动
- It is not allowed to rename or repackage the original archive “sapjco3.jar“
- 一些设计上的基本常识(转载)
- 茶百科 android 论文,基于android平台手机茶百科开发_学位论文.doc
- 怎么抓取屏幕截图计算机考试时间,定时抓屏快照(电脑截屏工具)V4.8 最新版
- hash表冲突处理方法
- java图片工具类_Java 下载图片下载文件 工具类
- 颜色选择器(拾色器)
- 通过 SiteServer CMS 推进政府网站集约化、集群化建设
- Ubuntu 18.04 究极美化教程
- U-Net-Convolutional Networks for Biomedical Image Segmentation论文翻译——中文版
- Usage of API documented as @since 1.8+”报错的解决办法
- 我对区块链行业的一点不成熟的想法
- poi生成word文档 表格自适应问题
- 财富宣言_必须阅读:休闲游戏宣言
- java程序员面试宝典(刘磊版)笔记
- 保底掉落装备matlab,DNF团本减负计划 保底深渊票史诗装备删除
- 全球及中国第五代移动通信技术(5G)产业建设现状与应用发展方向分析报告2022年
- 检测计算机命令,磁盘检测命令chkdsk的使用方法