junit5和junit4_JUnit 5 –条件

junit5和junit4

最近,我们了解了JUnit的新扩展模型以及它如何使我们能够将自定义行为注入测试引擎。 我向你保证要看情况。 现在就开始吧!

条件允许我们在应该执行或不应该执行测试时定义灵活的标准。 它们的正式名称是“ 条件测试执行” 。

总览

本系列中有关JUnit 5的其他文章:

  • 建立
  • 基本
  • 建筑
  • 扩展模型
  • 条件
  • 注射

在新兴的《 JUnit 5用户指南》中可以找到您将在此处阅读的更多内容以及更多内容。 请注意,它基于Alpha版本,因此可能会发生变化。

确实,我们鼓励我们提出问题或提出请求,以便JUnit 5可以进一步改进。 请利用这个机会! 这是我们帮助JUnit帮助我们的机会,因此,如果您能在这里看到一些改善,请确保将其上游 。

如有必要,此帖子将得到更新。 我在这里显示的代码示例可以在GitHub上找到 。

条件扩展点

还记得我们所说的扩展点吗? 没有? 简而言之:它们很多,每个都与特定的接口有关。 可以将这些接口的实现传递给JUnit(带有@ExtendWith批注),它将在适当的时候调用它们。

对于条件,需要关注两个扩展点:ContainerExecutionCondition和TestExecutionCondition。

public interface ContainerExecutionCondition extends Extension {/*** Evaluate this condition for the supplied ContainerExtensionContext.** An enabled result indicates that the container should be executed;* whereas, a disabled result indicates that the container should not* be executed.** @param context the current ContainerExtensionContext*/ConditionEvaluationResult evaluate(ContainerExtensionContext context);}public interface TestExecutionCondition extends Extension {/*** Evaluate this condition for the supplied TestExtensionContext.** An enabled result indicates that the test should be executed;* whereas, a disabled result indicates that the test should not* be executed.** @param context the current TestExtensionContext*/ConditionEvaluationResult evaluate(TestExtensionContext context);}

ContainerExecutionCondition确定是否执行容器中的测试。 在带有注释测试方法的通常情况下,测试类将是容器。 在同一场景中,各个测试方法的执行由TestExecutionConditions确定。

(我说“在通常情况下”是因为不同的测试引擎对容器和测试的解释可能非常不同。类和方法只是最常见的解释。)

这已经差不多了。 任何条件都应实现这些接口中的一个或两个,并在其评估实现中进行所需的检查。

@已停用

最简单的条件是甚至没有评估的条件:如果存在我们手工制作的注释,我们总是总是禁用测试。

因此,让我们创建@Disabled:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(@DisabledCondition.class)
public @interface Disabled { }

和匹配的扩展名:

public class DisabledConditionimplements ContainerExecutionCondition, TestExecutionCondition {private static final ConditionEvaluationResult ENABLED =ConditionEvaluationResult.enabled("@Disabled is not present");@Overridepublic ConditionEvaluationResult evaluate(ContainerExtensionContext context) {return evaluateIfAnnotated(context.getElement());}@Overridepublic ConditionEvaluationResult evaluate(TestExtensionContext context) {return evaluateIfAnnotated(context.getElement());}private ConditionEvaluationResult evaluateIfAnnotated(AnnotatedElement element) {Optional<Disabled> disabled = AnnotationUtils.findAnnotation(element, Disabled.class);if (disabled.isPresent())return ConditionEvaluationResult.disabled(element + " is @Disabled");return ENABLED;}}

像馅饼一样容易,对吧? 也是正确的,因为它与真正的@Disabled实现几乎相同。 只有两个小区别:

  • 官方注释不需要随身携带扩展名,因为它是默认注册的。
  • 可以给出一个原因,当跳过禁用的测试时会记录该原因。

小警告(当然,您有什么想法?):AnnotationUtils是内部API,但其功能可能很快就会正式可用 。

现在,让我们尝试一些不那么琐碎的事情。

@DisabledOnOs

如果我们使用的是正确的操作系统,也许我们只想运行一些测试。

简单的解决方案

同样,我们从注释开始:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(OsCondition.class)
public @interface DisabledOnOs {OS[] value() default {};}

这次需要一个值,如果不是,则取一堆,即不应运行测试的操作系统。 OS只是一个枚举,每个操作系统都有一个值。 而且它有一个方便的静态OS define()方法,您猜对了,它确定了代码在其上运行的操作系统。

这样,让我们​​转向OsCondition。 它必须检查注释是否存在,但还要检查当前的操作系统是否是提供给注释的操作系统之一。

public class OsCondition implements ContainerExecutionCondition, TestExecutionCondition {// both `evaluate` methods forward to `evaluateIfAnnotated` as aboveprivate ConditionEvaluationResult evaluateIfAnnotated(AnnotatedElement element) {Optional<DisabledOnOs> disabled = AnnotationUtils.findAnnotation(element, DisabledOnOs.class);if (disabled.isPresent())return disabledIfOn(disabled.get().value());return ENABLED;}private ConditionEvaluationResult disabledIfOn(OS[] disabledOnOs) {OS os = OS.determine();if (Arrays.asList(disabledOnOs).contains(os))return ConditionEvaluationResult.disabled("Test is disabled on " + os + ".");elsereturn ConditionEvaluationResult.enabled("Test is not disabled on " + os + ".");}}

我们可以如下使用它:

@Test
@DisabledOnOs(OS.WINDOWS)
void doesNotRunOnWindows() {assertTrue(false);
}

真好

少礼

但是我们可以做得更好! 借助JUnit的可自定义注释,我们可以使此条件更加平滑:

@TestExceptOnOs(OS.WINDOWS)
void doesNotRunOnWindowsEither() {assertTrue(false);
}

要实现@TestExceptOnOs,只需执行以下操作就可以了:

@Retention(RetentionPolicy.RUNTIME)
@Test
@DisabledOnOs(/* somehow get the `value` below */)
public @interface TestExceptOnOs {OS[] value() default {};}

当执行测试并扫描OsCondition :: evaluateIfAnnotated中的@DisabledOnOs时,我们会发现它在@TestExceptOnOs上进行了元注释,并且我们的逻辑将正常工作。 但是我找不到一种方法使@DisabledOnOs可以访问提供给@TestExceptOnOs的OS值。 :( (你能?)

下一个最佳选择是对新注释简单地使用相同的扩展名:

@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(OsCondition.class)
@Test
public @interface TestExceptOnOs {OS[] value() default {};}

然后我们拉皮条OsCondition :: evaluateIfAnnotated包括新的案例…

private ConditionEvaluationResult evaluateIfAnnotated(AnnotatedElement element) {Optional<DisabledOnOs> disabled = AnnotationUtils.findAnnotation(element, DisabledOnOs.class);if (disabled.isPresent())return disabledIfOn(disabled.get().value());Optional<TestExceptOnOs> testExcept = AnnotationUtils.findAnnotation(element, TestExceptOnOs.class);if (testExcept.isPresent())return disabledIfOn(testExcept.get().value());return ConditionEvaluationResult.enabled("");
}

……我们完成了。 现在我们确实可以按照我们希望的方式使用它。

抛光

创建倒置的注释(如果不在指定的操作系统之一上禁用,则完全相同),但是有了它们,改进的名称和静态导入,我们可以在这里结束:

@TestOn(WINDOWS)
void doesNotRunOnWindowsEither() {assertTrue(false);
}

还不错吧?

junit-5-条件

在CC-BY 2.0下由CWCS托管主机发布

@DisabledIfTestFails

让我们再尝试一件事–这次我们将使其变得非常有趣! 假设有很多(集成?)测试,并且如果其中一个测试由于特定的异常而失败,那么其他测试也必然会失败。 因此,为了节省时间,我们想禁用它们。

那么我们在这里需要什么呢? 显而易见,我们必须以某种方式收集在测试执行过程中引发的异常。 这必须与测试类的生存期绑定,因此我们不会禁用测试,因为某些异常会在完全不同的测试类中发生。 然后,我们需要一个条件实现,该条件实现检查是否抛出了特定异常,如果存在则禁用测试。

收集例外

查看扩展点列表,我们发现“异常处理”。 相应的接口看起来很有希望:

/*** ExceptionHandlerExtensionPoint defines the API for Extension Extensions* that wish to react to thrown exceptions in tests.** [...]*/
public interface ExceptionHandlerExtensionPoint extends ExtensionPoint {/*** React to a throwable which has been thrown by a test method.** Implementors have to decide if they* * - Rethrow the incoming throwable* - Throw a newly constructed Exception or Throwable* - Swallow the incoming throwable** [...]*/void handleException(TestExtensionContext context, Throwable throwable)throws Throwable;
}

因此,我们将实现handleException来存储然后重新抛出异常。

您可能还记得我写的有关扩展和状态的内容:

引擎在实例化扩展时以及将实例保留多长时间时不做任何保证,因此它们必须是无状态的。 他们需要维护的任何状态都必须写入JUnit并从中加载。

好的,所以我们使用商店。 有效地收集了我们想要记住的东西。 我们可以通过传递给大多数扩展方法的扩展上下文来访问它。 稍作修改后发现,每个上下文都有其自己的存储,因此我们必须决定访问哪个上下文。

每个测试方法(TestExtensionContext)和整个测试类(ContainerExtensionContext)都有一个上下文。 请记住,我们想将在执行所有测试期间抛出的所有异常存储在一个类中,但不能存储更多,即不存储其他测试类抛出的异常。 事实证明,ContainerExtensionContext及其存储正是我们需要的。

因此,这里我们获取容器上下文并使用它来存储一组引发的异常:

private static final Namespace NAMESPACE = Namespace.of("org", "codefx", "CollectExceptions");
private static final String THROWN_EXCEPTIONS_KEY = "THROWN_EXCEPTIONS_KEY";@SuppressWarnings("unchecked")
private static Set<Exception> getThrown(ExtensionContext context) {ExtensionContext containerContext = getAncestorContainerContext(context).orElseThrow(IllegalStateException::new);return (Set<Exception>) containerContext.getStore(NAMESPACE).getOrComputeIfAbsent(THROWN_EXCEPTIONS_KEY,ignoredKey -> new HashSet<>());
}private static Optional<ExtensionContext> getAncestorContainerContext(ExtensionContext context) {Optional<ExtensionContext> containerContext = Optional.of(context);while (containerContext.isPresent()&& !(containerContext.get() instanceof ContainerExtensionContext))containerContext = containerContext.get().getParent();return containerContext;
}

现在添加一个异常很简单:

@Override
public void handleException(TestExtensionContext context, Throwable throwable)throws Throwable {if (throwable instanceof Exception)getThrown(context).add((Exception) throwable);throw throwable;
}

实际上,这本身就是一个有趣的扩展。 也许它也可以用于分析。 无论如何,我们将要查看抛出的异常,因此我们需要一个公共方法:

public static Stream<Exception> getThrownExceptions(ExtensionContext context) {return getThrown(context).stream();
}

有了这个扩展,任何其他扩展都可以检查到目前为止已经抛出了哪些异常。

禁用

其余部分与以前非常相似,因此让我们快速了解一下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(DisabledIfTestFailedCondition.class)
public @interface DisabledIfTestFailedWith {Class<? extends Exception>[] value() default {};}

请注意,我们仅在方法上允许使用此注释。 在测试类上使用它可能很有意义,但现在让我们保持简单。 因此,我们仅实现TestExecutionCondition。 在检查了是否存在我们的注释之后,我们使用用户提供的异常类调用disableIfExceptionWasThrown:

private ConditionEvaluationResult disableIfExceptionWasThrown(TestExtensionContext context,Class<? extends Exception>[] exceptions) {return Arrays.stream(exceptions).filter(ex -> wasThrown(context, ex)).findAny().map(thrown -> ConditionEvaluationResult.disabled(thrown.getSimpleName() + " was thrown.")).orElseGet(() -> ConditionEvaluationResult.enabled(""));
}private static boolean wasThrown(TestExtensionContext context, Class<? extends Exception> exception) {return CollectExceptionExtension.getThrownExceptions(context).map(Object::getClass).anyMatch(exception::isAssignableFrom);
}

把它放在一起

如果在之前抛出特定类型的异常,这就是我们使用这些批注禁用测试的方式:

@CollectExceptions
class DisabledIfFailsTest {private static boolean failedFirst = false;@Testvoid throwException() {System.out.println("I failed!");failedFirst = true;throw new RuntimeException();}@Test@DisabledIfTestFailedWith(RuntimeException.class)void disableIfOtherFailedFirst() {System.out.println("Nobody failed yet! (Right?)");assertFalse(failedFirst);}}

摘要

哇,那是很多代码! 但是到目前为止,我们真的知道如何在JUnit 5中实现条件:

  • 创建所需的注释和@ExtendWith条件实现
  • 实现ContainerExecutionCondition,TestExecutionCondition或同时实现
  • 检查是否存在新的注释
  • 进行实际检查并返回结果

我们还看到,这可以与其他扩展点结合使用,如何使用商店来保留信息,并且自定义注释可以使扩展使用起来更加优雅。

有关标记扩展点的更多乐趣,请在讨论参数注入时查看本系列的下一篇文章。

翻译自: https://www.javacodegeeks.com/2016/05/junit-5-conditions.html

junit5和junit4

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336210.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python opencv输出mp4_10分钟学会使用YOLO及Opencv实现目标检测

点击边框调出视频工具条 计算机视觉领域中&#xff0c;目标检测一直是工业应用上比较热门且成熟的应用领域&#xff0c;比如人脸识别、行人检测等&#xff0c;国内的旷视科技、商汤科技等公司在该领域占据行业领先地位。相对于图像分类任务而言&#xff0c;目标检测会更加复杂一…

捍卫者usb管理控制系统_捍卫Java

捍卫者usb管理控制系统因此&#xff0c;我们不时发布了一本电子书&#xff0c;名为“十大Java性能问题” 。 毫无例外&#xff0c;一些人回答了一些“问题是您正在使用Java”。 显然&#xff0c;Java一直在受到批评&#xff0c;人们已经预测了它的消亡已有一段时间了。 当然&a…

html怎么上传qq空间,qq空间怎么上传照片

当我们想要把照片上传到qq空间里&#xff0c;应该怎么办呢?下面就让学习啦小编告诉你空间上传照片的方法&#xff0c;希望对大家有所帮助。空间上传照片的方法打开QQ主界面&#xff0c;在主界面头像的右则有个小星星&#xff0c;那就是进入空间的快捷方式&#xff0c;点一下小…

android gridview控件使用详解_Android开发实现自定义日历、日期选择控件

点击上方蓝字关注 ??来源&#xff1a; wenzhihao123https://www.jianshu.com/p/a2f102c728ce前言最近项目需要日历效果&#xff0c;考虑用第三方的反而不太适合设计需求&#xff0c;修改复杂&#xff0c;与其这样不入自己重新写一个干净的控件。虽不是什么牛逼控件&#xff0…

HTML设置字体颜色1008无标题,如何在HTML中设置字体颜色,你知道这几种方式吗?...

color设置字体颜色在color设置字体颜色之前&#xff0c;我们首先了解color在css中有几种取值方式&#xff0c;一共有4种方式&#xff0c;若有不全还请在评论区告知谢谢&#xff0c;4种方式如下&#xff1a;十六进制、十进制、 英文单词、十六进制的缩写。现在让我们进入字体颜色…

gram矩阵_Skip-gram

Skip-gram标签(空格分隔)&#xff1a;NLP一. skip-gram和cbow的对比 skip-gram与cbow相比&#xff0c;好处在于对于不常用的词&#xff0c;skip-gram的效果要更好&#xff1b;举个简单的例子&#xff0c;一个句子w1w2w3w4&#xff0c;window_size1&#xff1b;对于cbow&#xf…

C++ 11 深度学习(十五)多线程

线程创建 方式一:调用函数 #include<thread>void CreateThread() {int a100;cout<<"This is Thread: "<<a<<endl; }int main() {thread Threadone(CreateThread);//join是一种阻塞的方式&#xff0c;需要子线程处理完毕之后&#xff0c;…

计算机的好处和坏处的英语作文,电脑的利弊英语作文

电脑的利弊英语作文在学习、工作或生活中&#xff0c;大家都写过作文吧&#xff0c;通过作文可以把我们那些零零散散的思想&#xff0c;聚集在一块。那么你有了解过作文吗&#xff1f;下面是小编为大家整理的电脑的利弊英语作文&#xff0c;希望能够帮助到大家。Computer is in…

servlet容器_SpringBoot是否内置了Servlet容器?

SpringBoot是否内置了Servlet容器&#xff1f;SpringBoot内置了Servlet容器&#xff0c;这样项目的发布、部署就不需要额外的Servlet容器&#xff0c;直接启动jar包即可。SpringBoot官方文档上有一个小章节内置servlet容器支持用于说明内置Servlet的相关问题。在SpringBoot源码…

计算机专业开学要带电脑吗,大学上课要带电脑吗

大学刚开学&#xff0c;上课的时候学生们要不要带电脑呢&#xff0c;想必这个问题一直对还没进入大学的准大学生来说很困扰&#xff0c;下面是小编整理的详细内容&#xff0c;一起来看看吧&#xff01;大学上课要带电脑吗大学上课能否带电脑需要看老师的要求。大学课程书本知识…

突然讨厌做前端,讨厌代码_不要讨厌HATEOAS

突然讨厌做前端,讨厌代码或我如何学会不再担心和爱HATEOAS REST已成为实现Web服务的事实上的解决方案&#xff0c;至少已成为一种流行的解决方案。 这是可以理解的&#xff0c;因为REST在使用HTTP规范时提供了一定程度的自我文档。 它经久耐用&#xff0c;可扩展&#xff0c;并…

【WebRTC---进阶篇】(三)各流媒体服务器的比较

多人音视频架构 Mesh方案 多对多大多进行P2P,在国内P2P直连穿越会出现很大问题。 MCU方案 客户端连接后,对应每个终端都有一个模块进项上传。再将音视频进行拆分解码。进行混屏,压缩编码分别推动给每个终端。 SFU方案 sfu不进行编解码,只是进行转发。只对订阅的终端进行…

汇编 cmp_汇编复习

第一章计算机组成五部分&#xff1a;&#xff08;运算器、控制器&#xff09;、存储器、输入/输出设备↑↑ CPU ↑↑ ↑内存↑三条总线&#xff1a;控制总线、地址总线、数据总线不同进制及BCD码的转换特殊ascll ‘0’~‘9’—— 30H ~ 39H‘A’~‘F’—— 41H ~ 46H回车 —— …

junit5和junit4_JUnit 5 –设置

junit5和junit42015年11月&#xff0c; JUnit Lambda团队展示了他们的原型 。 此后&#xff0c;该项目更名为JUnit 5&#xff0c;并于2016年2月发布了Alpha版本。我们将在一系列简短文章中进行探讨&#xff1a; 建立 基本 建筑 条件 注射 … 本节讨论JUnit 5的设置&…

markdown 生成目录_github上如何为markdown文件生成目录

写在前面熟悉markdown都知道可以使用[TOC]自动生成markdown文件的标题目录&#xff0c;比如在typora&#xff0c;vscode(需要插件)等本地编辑器中&#xff0c;或者在CSDN等网页编辑器中&#xff0c;但是github却不支持[TOC]标签&#xff0c;至于为什么不支持感兴趣的可以深入搜…

【WebRTC---进阶篇】(五)mediasoup的信令系统

mediasoup demo分析 app 客户端部分 broadcasters 推拉流部分 server 服务端部分 config.js 相当于一个配置文件&#xff0c;获取一些基本配置信息。获取的信息来交给server.js。 server.js 先从config.js获取信息&#xff0c;然后启动HTTPS webSocket服务等&#xff0c;…

axure html尺寸,axure怎么确定尺寸

回答&#xff1a;您好如做的是室内设计的话&#xff0c;那么来说可能会些参数提供给您的(例如长宽高)如果没有参数的话&#xff0c;只要把比例做好就可以了。只要比例做好了&#xff0c;东西看起来就自然像。至于教程的话&#xff0c;一般录制教程前都会有做好准备的&#xff0…

exe打包工具哪个最好_为你的 Python 程序写个启动工具箱

到目前为止&#xff0c;公众号已经介绍了不少图形界面的软件&#xff0c;比如猜数游戏、PDF阅读器、贪吃蛇游戏、天气查询软件、PDF 阅读器等。为了方便他人使用&#xff0c;我们常把图形界面打包成 exe 文件。但是如果我们只是为了自己使用方便的话&#xff0c;我们有必要把程…

【WebRTC---进阶篇】(六)SELECT网络模型

select函数原型 int WSAAPI select(_In_ int nfds,_Inout_opt_ fd_set FAR * readfds,_Inout_opt_ fd_set FAR * writefds,_Inout_opt_ fd_set FAR * exceptfds,_In_opt_ const struct timeval FAR * timeout); 函数功能:监视多个文件描述符的状态变化,在IO中负责IO的第一步…

计算机管理没有打印机列队,在Windows清除打印队列如果打印机被卡住,也没有打印输出...

我相信自己已经勾起回忆一拉似曾相识 &#xff0c;右侧的主题&#xff1f; 我们每个人&#xff0c;在一段时间或其他&#xff0c;都在打印过程中面临的问题&#xff0c;特别是给打印命令&#xff0c;并打印输出不休后等待。 无论是在家里还是办公室里&#xff0c;那就是我们所有…