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

server/2024/9/22 21:34:38/

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/server/11391.html

相关文章

数据结构面试常见问题

在IT行业&#xff0c;特别是软件开发和算法工程师的面试中&#xff0c;数据结构知识是必不可少的一部分。面试官通过提问数据结构相关问题&#xff0c;可以评估候选人的编程基础、逻辑思维和解决问题的能力。本文将对数据结构面试中常见的问题进行详细解析&#xff0c;并给出相…

树和二叉树(一)

一、树 非线性数据结构&#xff0c;在实际场景中&#xff0c;存在一对多&#xff0c;多对多的情况。 树( tree&#xff09;是n (n>0&#xff09;个节点的有限集。当n0时&#xff0c;称为空树。 在任意一个非空树中&#xff0c;有如下特点。 1.有且仅有一个特定的称为根的节点…

Python全栈开发前端与后端的完美融合

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在当今互联网时代&#xff0c;全栈开发已经成为了一种趋势。全栈开发者具备前端和后端开发的…

51.函数嵌套和链式访问

一.函数嵌套 在一个函数中调用另外一个函数叫做函数嵌套。举例&#xff1a; #include <stdio.h>int max(int,int); int min(int,int); int max_or_min(int,int,int);void main(void) {int ret;ret max_or_min(1,1,2);printf("ret is %d\n",ret); }int max(in…

spring.factories中配置ApplicationContextInitializer实现类却不起作用

自定义了一个ApplicationContextInitializer的实现类如下 public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {Overridepublic void initialize(ConfigurableApplicationContext applicationCon…

2024年Java接单平台强力推荐!各个都知名!

Java这几年真卷飞了&#xff0c;一点都不夸张。因此&#xff0c;很多程序员朋友都已经试着转方向、换赛道了。试着接单、找私活就是一大途径。当然&#xff0c;特别是有技术、又有相对空闲时间的朋友&#xff0c;更值得一试。既是增加收入的捷径&#xff0c;又可以提升自我——…

Linux进程地址空间及其页表

文章目录 一、引言二、Linux进程地址空间的概念1、进程地址空间定义2、进程地址空间的组成3、进程地址空间与物理内存的关系 三、页表与内存映射1、页表的定义及作用2、页表的缺页中断 三、进程的写时拷贝 一、引言 在Linux中&#xff0c;进程管理是其核心功能之一&#xff0c…

搜维尔科技:Haption Virtuose 6D TAO 力反馈设备,专为机器人的和遥操作市场设计

HaptionVirtuose 6D TAO 力反馈设备&#xff0c;专为机器人的和遥操作市场设计 搜维尔科技&#xff1a;Haption Virtuose 6D TAO 力反馈设备&#xff0c;专为机器人的和遥操作市场设计