【单元测试】Junit 4(八)--junit4 内置Rule
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 {
@Rule
public final TestName name = new TestName();
@Test
public void testA() {
assertEquals("testA", name.getMethodName());
}
@Test
public 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 {
@Rule
public TemporaryFolder folder= new TemporaryFolder();
@Test
public 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();
@Rule
public ExternalResource resource = new ExternalResource() {
@Override
protected void before() throws Throwable {
myServer.connect();
};
@Override
protected void after() {
myServer.disconnect();
};
};
@Test
public 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 };
@Rule
public ErrorCollector errorCollector = new ErrorCollector();
/*
* 下面这个测试,会报告两个failures。这一点和下面的checkSucceeds测试不同
*/
@Test
public 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 Failures
errorCollector.checkThat(2 * multiple, is(multipleOf2));
multiple++;
}
}
/*
* 下面代码中有两个断言会失败,但每次运行JUnit框架只会报告一个。这一点和上面的checkThat测试不同,可以对比一下。
*/
@Test
public 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个错误
*/
@Test
public 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 error
testAddingAnError(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 {
@Rule
public Verifier collector = new Verifier() {
@Override
protected void verify() {
sequence += " verify ";
}
};
@Test
public void example() {
sequence += "test";
}
@Test
public void example2() {
sequence += "test2";
}
@After
public void after() {
sequence += " after";
}
}
@Test
public 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;
@Rule
public TestRule watchman = new TestWatcher() {
@Override
public Statement apply(Statement base, Description description) {
Statement s = super.apply(base, description);
watchedLog="";
System.out.println("watch apply.");
return s;
}
@Override
protected void succeeded(Description description) {
watchedLog += description.getDisplayName() + " " + "success!";
System.out.println("watch succeed:"+watchedLog);
}
@Override
protected void failed(Throwable e, Description description) {
watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName();
System.out.println("watch failed:"+watchedLog);
}
@Override
protected void starting(Description description) {
super.starting(description);
System.out.println("watch starting.");
}
@Override
protected void finished(Description description) {
super.finished(description);
System.out.println("watch finished.");
}
};
@Rule
public Verifier collector = new Verifier() {
@Override
protected void verify() {
System.out.println("@Verify:"+watchedLog);
}
};
@Test
public void fails() {
System.out.println("in fails");
assertThat("ssss", is("sss"));
}
@Test
public void succeeds() {
System.out.println("in succeeds");
}
@After
public void after() {
System.out.println("@After");
}
}
1.7 Timeout
对于添加了TimeoutRule 的测试类,当测试类中的测试方法执行超过TimeoutRule 配置的时间时,测试方法执行就会被标记为失败
public class TimeoutRuleTest {
@Rule
public Timeout globalTimeout = Timeout.seconds(5);
@Test
public void timeout() throws InterruptedException {
TimeUnit.SECONDS.sleep(10);
}
@Test
public void onTime() throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
执行上面测试用例,onTime方法执行通过,timeout()方法则抛出TestTimedOutException:
org.junit.runners.model.TestTimedOutException: test timed out after 5 seconds
还有很多Rule就不一一介绍了
【单元测试】Junit 4(八)--junit4 内置Rule的更多相关文章
- Python学习(八) —— 内置函数和匿名函数
一.递归函数 定义:在一个函数里调用这个函数本身 递归的最大深度:997 def func(n): print(n) n += 1 func(n) func(1) 测试递归最大深度 import sy ...
- springboot(八)内置SpringMvc静态文件地址修改
参考:作者:恒宇少年链接:https://www.jianshu.com/p/c6ab1081fd5f 介绍: SpringMVC大家都不陌生,而被SpringBoot集成的SpringMVC除了 ...
- JUnit源码分析 - 扩展 - 自定义Rule
JUnit Rule简述 Rule是JUnit 4.7之后新加入的特性,有点类似于拦截器,可以在测试类或测试方法执行前后添加额外的处理,本质上是对@BeforeClass, @AfterClass, ...
- python基础-内置函数详解
一.内置函数(python3.x) 内置参数详解官方文档: https://docs.python.org/3/library/functions.html?highlight=built#ascii ...
- JavaWeb学习----JSP内置对象详解
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Jsp(3):内置对象和四种域对象的理解
由来:在jsp开发中,会频繁使用到一些对象 .例如HttpSession,ServletContext,ServletContext,HttpServletRequet.所以Sun公司设计Jsp时,在 ...
- JSP三个指令及9个内置对象
注:本文编写方便自己以后用到时查阅 三大指令:include. page.taglib include指令: 作用: 在当前页面用于包含其他页面 语法: <%@include file=&qu ...
- ASP.NET 内置对象涉略
一.ASP.NET中内置的常用对象的介绍 本文列举了ASP.NET 的八个内置对象,其中前五个是比较常用的. 1.Response Response 对象用于从服务器向用户发送输出的结果. Write ...
- python基础——内置函数
python基础--内置函数 一.内置函数(python3.x) 内置参数详解官方文档: https://docs.python.org/3/library/functions.html?highl ...
- 咸鱼入门到放弃8--jsp<三>jsp内置对象
NO. 内置对象 类型 1 pageContext javax.servlet.jsp.PageContext 2 request javax.servlet.http.HttpServletRequ ...
随机推荐
- MAMP redis.conf 位置 , nginx.conf位置
/Applications/MAMP PRO.app/Contents/Resources/redis.conf /Applications/MAMP/conf/nginx/nginx.conf /A ...
- 目前为止最完善专业的微信小程序商城
购买商业版(368元): http://market.zhenzikj.com/detail/82.html帮助文档:https://www.kancloud.cn/crmeb/crmeb/66242 ...
- openSUSE 播放使用VLC播放视频
openSUSE 使用VLC播放视频 linux视频播放 为什么 通常我们在安装号vlc后,由于版权的原因,是无法获取视频的解码器的.我们需要下载第三方的解码器帮助我们进行解码. 过程如下: 添加pa ...
- bzoj 4407
莫比乌斯反演 还是推式子: 设$f(n)=n^{k}$ 那就是上一道题了 推的过程如下: $\sum_{i=1}^{a}\sum_{j=1}^{b}f(gcd(i,j))$ $\sum_{i=1}^{ ...
- COLMAP论文阅读笔记——sfm算法、不定期更新
文章目录 structure from motion revisited 第一步 对应点搜索 特征提取feature extraction 匹配matching 几何验证geometric verif ...
- CentOS 7 部署Memcached服务器——超级详细
操作系统:CentOS 7.x 64位实现目的:安装部署Memcached服务器 一.防火墙设置CentOS 7.x默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭f ...
- 第10章 带有依赖注入的服务配置(ASP.NET Core in Action, 2nd Edition)
第2部分 构建完整的应用程序 我们在第一部分中讨论了很多内容.您看到了ASP.NET Core应用程序是如何由中间件组成的,我们主要关注RazorPages框架.您了解了如何使用Razor语法构建传统 ...
- 修改浏览器搜索引擎:设置网址格式(用“%s”代替搜索字词)
浏览器搜索引擎设置,如何填写网址格式(用"%s"代替搜索字词)? 以下收集部分: 综合检索 名称 关键字 网址(用"%s"代替搜索字词) 必应 cn.bing. ...
- 2003031120—廖威—Python数据分析第三周作业—numpy的简单操
项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/pexy/20sj 这个作业要求链接 https://edu.cnblogs.com/campus/pexy ...
- PyQt5 & PySide2信号与槽机制1
pyside2&pyqt5的信号与槽机制 1.信号与槽的两种写法 第一种情况: from PySide2 import QtWidgets, QtCore import sys if __na ...