【单元测试】Junit 4--junit4 内置Rule

ops/2024/10/19 21:34:51/

1.0 Rules

​ Rules允许非常灵活地添加或重新定义一个测试类中每个测试方法的行为。测试人员可以重复使用或扩展下面提供的Rules之一,或编写自己的Rules。

1.1 TestName

​ TestName Rule使当前的测试名称在测试方法中可用。用于在测试执行过程中获取测试方法名称。在starting()中记录测试方法名,在getMethodName()中返回

例如:

import static org.junit.Assert.*;import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;public class NameRuleTest {@Rulepublic final TestName name = new TestName();@Testpublic void testA() {assertEquals("testA", name.getMethodName());}@Testpublic void testB() {assertEquals("testB", name.getMethodName());}
}

1.2 TemporaryFolder

​ TemporaryFolder Rule允许创建文件和文件夹,这些文件和文件夹在测试方法结束时被删除(无论通过还是失败)。默认情况下,如果资源不能被删除,则不会抛出异常。

import java.io.*;import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;public class HasTempFolder {@Rulepublic TemporaryFolder folder= new TemporaryFolder();@Testpublic void testUsingTempFolder() throws IOException {File createdFile = folder.newFile("myfile.txt");File createdFolder = folder.newFolder("subfolder");// ...}}

TemporaryFolder#newFolder(String… folderNames)可以根据输入的参数创建目录。如果是多级目录,可以递归创建。

TemporaryFolder#newFile()可以创建一个随机名字的临时文件;

TemporaryFolder##newFolder() 可以创建一个随机名字的临时目录。

1.3 ExternalResource

​ ExternalResource是一个规则(如TemporaryFolder)的基类,它在测试前设置了一个外部资源(一个文件、套接字、服务器、数据库连接等),并保证在测试后将其拆除。

可以设置测试前后需要做的事情(比如:文件、socket、服务、数据库的连接与关闭)。

 public static class UsesExternalResource {Server myServer = new Server();@Rulepublic ExternalResource resource = new ExternalResource() {@Overrideprotected void before() throws Throwable {myServer.connect();};@Overrideprotected void after() {myServer.disconnect();};};@Testpublic void testFoo() {new Client().run(myServer);}}

ExternalResource#before会在每个测试之前处理;#after会在每个测试之后处理;

关于ExternalResource与@Before已经@After等标记步骤的执行顺序,我们会在本文后面部分介绍。

1.4 ErrorCollector

ErrorCollector这个Rule,在出现一个错误后,还可以让测试继续进行下去。

他提供三个方法:

  • checkThat(final T value, Matcher matcher)
  • checkSucceeds(Callable callable)
  • addError(Throwable error)

前面两个是用来处理断言的,最后一个是添加错误至错误列表中。

看下面例子:

 package mytest;import static org.hamcrest.CoreMatchers.is;import static org.junit.Assert.assertThat;import java.util.concurrent.Callable;import org.junit.Rule;import org.junit.Test;import org.junit.rules.ErrorCollector;public class JUnitCoreErrorControllerRuleTest {private final int multiplesOf2[] = { 0, 2, 4, 7, 8, 11, 12 };@Rulepublic ErrorCollector errorCollector = new ErrorCollector();/** 下面这个测试,会报告两个failures。这一点和下面的checkSucceeds测试不同*/@Testpublic void testMultiplesOf2() {int multiple = 0;for (int multipleOf2 : multiplesOf2) {// Will count the number of issues in this list// - 3*2 = 6 not 7, 5*2 = 10 not 11 : 2 FailureserrorCollector.checkThat(2 * multiple, is(multipleOf2));multiple++;}}/** 下面代码中有两个断言会失败,但每次运行JUnit框架只会报告一个。这一点和上面的checkThat测试不同,可以对比一下。*/@Testpublic void testCallableMultiples() {errorCollector.checkSucceeds(new Callable<Object>() {public Object call() throws Exception {assertThat(2 * 2, is(5));assertThat(2 * 3, is(6));assertThat(2 * 4, is(8));assertThat(2 * 5, is(9));return null;}});}/** 下面运行时,会报告2个错误*/@Testpublic void testAddingAnError() {assertThat(2 * 2, is(4));errorCollector.addError(new Throwable("Error Collector added an error"));assertThat(2 * 3, is(6));errorCollector.addError(new Throwable("Error Collector added a second error"));}}

运行结果:

 Failed tests: testCallableMultiples(mytest.JUnitCoreErrorControllerRuleTest): Expected: is <5>but: was <4>testMultiplesOf2(mytest.JUnitCoreErrorControllerRuleTest): Expected: is <7>but: was <6>testMultiplesOf2(mytest.JUnitCoreErrorControllerRuleTest): Expected: is <11>but: was <10>Tests in error: testAddingAnError(tangzhi.mytest.JUnitCoreErrorControllerRuleTest): Error Collector added an errortestAddingAnError(tangzhi.mytest.JUnitCoreErrorControllerRuleTest): Error Collector added a second error

从这个例子,可以看出:

  • ErrorCollector#checkThat 会报告测试中的每一个failures
  • ErrorCollector#checkSucceeds 只会检查是否成功,如果不成功,只报告第一个导致不成功的failure
  • ErrorCollector#addError 是添加一个错误(error)。

1.5 Verifier

如果,你想在每个测试之后,甚至是在@After之后,想检查些什么,就可以使用Verifier这个Rule.

看例子:

 private static String sequence;public static class UsesVerifier {@Rulepublic Verifier collector = new Verifier() {@Overrideprotected void verify() {sequence += " verify ";}};@Testpublic void example() {sequence += "test";}@Testpublic void example2() {sequence += "test2";}@Afterpublic void after() {sequence += " after";}}@Testpublic void verifierRunsAfterTest() {sequence = "";assertThat(testResult(UsesVerifier.class), isSuccessful());assertEquals("test after verify test2 after verify ", sequence);}

从上面例子可以看出:Verifier#verify针对每个测试都会运行一次,并且运行在@After步骤之后。

需要说明:如果某测试出现失败(fail),那么这个测试之后就不会做verify,这一点,可以结合下面的例子看出

1.6 TestWatcher

对测试的每个步骤进行监控。

看例子:

 package tangzhi.mytest;import static org.junit.Assert.*;  import static org.hamcrest.CoreMatchers.*;import org.junit.After;import org.junit.Rule;import org.junit.Test;import org.junit.rules.TestRule;import org.junit.rules.TestWatcher;import org.junit.rules.Verifier;import org.junit.runner.Description;import org.junit.runners.model.Statement;public class WatchmanTest {private static String watchedLog;@Rulepublic TestRule watchman = new TestWatcher() {@Overridepublic Statement apply(Statement base, Description description) {Statement s = super.apply(base, description);watchedLog="";System.out.println("watch apply.");return s;}@Overrideprotected void succeeded(Description description) {watchedLog += description.getDisplayName() + " " + "success!";System.out.println("watch succeed:"+watchedLog);}@Overrideprotected void failed(Throwable e, Description description) {watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName();System.out.println("watch failed:"+watchedLog);}@Overrideprotected void starting(Description description) {super.starting(description);System.out.println("watch starting.");}@Overrideprotected void finished(Description description) {super.finished(description);System.out.println("watch finished.");}};@Rulepublic Verifier collector = new Verifier() {@Overrideprotected void verify() {System.out.println("@Verify:"+watchedLog);}};@Testpublic void fails() {System.out.println("in fails");assertThat("ssss", is("sss"));}@Testpublic void succeeds() {System.out.println("in succeeds");}@Afterpublic void after() {System.out.println("@After");}}

1.7 Timeout

对于添加了TimeoutRule 的测试类,当测试类中的测试方法执行超过TimeoutRule 配置的时间时,测试方法执行就会被标记为失败

public class TimeoutRuleTest {@Rulepublic Timeout globalTimeout = Timeout.seconds(5);@Testpublic void timeout() throws InterruptedException {TimeUnit.SECONDS.sleep(10);}@Testpublic void onTime() throws InterruptedException {TimeUnit.SECONDS.sleep(2);}}

执行上面测试用例,onTime方法执行通过,timeout()方法则抛出TestTimedOutException:

org.junit.runners.model.TestTimedOutException: test timed out after 5 seconds

还有很多Rule就不一一介绍了

行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!


http://www.ppmy.cn/ops/5688.html

相关文章

Ubuntu Vs code配置ROS开发环境

文章目录 1.开发环境2.集成开发环境搭建2.1 安装Ros2.2 安装 Vs code2.3 安装vs code 插件 3.Vs code 配置ROS3.1 创建ROS工作空间3.2 从文件夹启动Vs code3.3 使用Vscode 编译ROS 空间3.4 使用Vs code 创建功能包 4.编写简单Demo实例4.1编写代码4.2编译与执行 1.开发环境 系统…

前端文件word Excel pdf PPT预览

组件一 <template><j-modal:visible"visible":fullscreen"fileType!other&&fileType!word"ok"handleOk":width"1200"cancel"handleCancel"><vue-office-docxv-if"fileTypeword":src"…

Docker - 简介

原文地址&#xff0c;使用效果更佳&#xff01; Docker - 简介 | CoderMast编程桅杆https://www.codermast.com/dev-tools/docker/docker-introduce.html Docker是什么&#xff1f; Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 D…

基于Springboot的职称评审管理系统

基于SpringbootVue的获取源码 联系方式 &#x1f447;&#x1f3fb;的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 评审条件 论坛信息 系统公告 后台登录…

【快速上手ESP32(基于ESP-IDFVSCode)】07-I2C(附BH1750实战代码)

I2C I2C&#xff0c;全称Inter-Integrated Circuit&#xff0c;是一种用于在集成电路之间进行短距离数据传输的通信协议。它最初由Philips&#xff08;现在的NXP半导体&#xff09;公司于1980年代初开发&#xff0c;现已成为广泛应用于电子设备之间通信的标准。 I2C协议简单、灵…

设计模式(020)行为型之备忘录模式

备忘录模式是一种行为型设计模式&#xff0c;用于在不破坏封装性的前提下捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态&#xff0c;以便之后可以将该对象恢复到之前的状态。这种模式通常用于需要记录对象状态历史、撤销操作或实现“回到过去”功能的场景。 在…

clickhouse学习笔记04

ClickHouse高可用之ReplicatedMergeTree引擎介绍 ClickHouse高可用架构准备-环境说明和ZK搭建 RPM安装ClickHouse 上传我们的clickhouse rpm文件。 安装&#xff1a; 中途需要输入用户名和密码 可以不设置 直接回车。 启动&#xff1a; 查看状态&#xff1a; 查看端口是否占用…

续传查询SQL不规范导致漏数的问题

查询交易记录的时候&#xff0c;&#xff0c;用户需要一页一页往下翻&#xff0c;每点击一次就会将续传接口包发到后端接口进行查询返回下一页的数据&#xff0c;续传接口有几个字段&#xff0c;是续传键值&#xff0c;后端的SQL会根据上次读取到的最后一条往后捞数据 有些同事…