我们之前处理异常的时候用到过Rules,当然还有很多其他规则。Rules允许弹性的添加或者重定义测试方法的行为。测试者可以重复使用或者扩展下面的某一个Rules,也可以写一个属于自己的规则。

这里先展示一张 TestRule的类图:

基本的规则有:

1.TemporaryFolder Rule

该规则建立的文件或者文件夹会在测试方法结束之后自动删除(不管测试pass还是fail)。默认情况下,即使资源删不掉也不会抛出异常。

import java.io.File;
import java.io.IOException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder; public class RuleTest {
@Rule
public TemporaryFolder folder=new TemporaryFolder(); @Test
public void test() throws IOException {
File aFile=folder.newFile("myfile.txt");
File aFolder=folder.newFolder("subfolder");
}
}
  • TemporaryFolder#newFolder(String...folderNames) 会递归深入的新建多个文件夹。
  • TemporaryFolder#newFile() 会新建一个带有随机名字的文件,#newFolder() 会新建一个带有随机名字的文件夹。
  • 从 4.13开始,如果测试结束之后资源不能被删除, TemporaryFolder 可以选择允许测试以 AssertionError的方式fail。但是这个特性只有在使用 #builder()的方法才可以被激活。为了向后兼容默认情况下还是不会抛出异常。

@Rule
public TemporaryFolder folder=TemporaryFolder.builder().assureDeletion().build();

2.ExternalResource Rules

ExternalResource用来对外部资源进行管理,包括在测试之前进行外部资源准备,测试之后对测试资源进行回收等工作。在创建测试文件、连接服务器、准备数据库连接等情况下用的比较多。

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource; public class RuleTest2 { @Rule
public ExternalResource external = new ExternalResource()
{
protected void before() throws Throwable
{
System.out.println("Perparing test data.");
System.out.println("Test data is Ready!");
} protected void after()
{
System.out.println("Cleaning test data.");
}
}; @Test
public void test1()
{
System.out.println("Test 1 executing...");
} @Test
public void test2()
{
System.out.println("Test 2 executing...");
} @Test
public void test3()
{
System.out.println("Test 3 executing...");
}
}

运行结果:

Perparing test data.
Test data is Ready!
Test 1 executing...
Cleaning test data.
Perparing test data.
Test data is Ready!
Test 2 executing...
Cleaning test data.
Perparing test data.
Test data is Ready!
Test 3 executing...
Cleaning test data.

3. ErrorCollector Rule

  • 继承自下面的Verifier Rule。ErrorCollector
    规则允许测试在第一个问题出现的时候继续执行,然后执行完之后一次性汇报结果。比如说测试一个表格里的所有的行,在第一行发现错误之后继续执行,直到所有
    的错误都发现才停止,然后一次性汇报所有的结果。
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector; public class TestRule3 {
@Rule
public ErrorCollector collector=new ErrorCollector();
@Test
public void test() {
collector.addError(new Throwable("first things went wrong!"));
collector.addError(new Throwable("second things went wrong!"));
}
}

运行结果:

4. Verifier Rule

它是ErrorCollector的父类。当每个测试结束之后会执行ErrorCollector的verify方法,如果执行不通过这个测试会被标记为fail。

import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Verifier; public class RuleTest4 {
String sequence=""; @Rule
public Verifier collector=new Verifier(){
@Override
protected void verify(){
System.out.println("this is verify...");
assertEquals("test verify ",sequence);
}
}; @Test
public void test01(){
System.out.println("this is testing 01...");
sequence += "test ";
} @Test
public void test02(){
System.out.println("this is testing 02...");
sequence="test verify ";
}
}

测试结果:

this is testing 01...
this is verify...
this is testing 02...
this is verify...

test01为 fail,而test02 pass。

5. TestWatchman/TestWatcher Rules

从4.9版本开始,TestWatcher开始代替 TestWatchman。TestWatcher实现了TestRule类,而不是MethodRule类。

TestWatchman从4.7版本开始引入,它使用 MethodRule,而MethodRule目前已经弃用。

TestWatcher 不会改变测试的任何行为,提供了 succeeded、failed、skipped、starting、finished方法用来监控一个测试方法生命周期的各个阶段,所有方法都包含一 个 org.junit.runner.Description 类型的参数用来描述当前执行的测试。

import static org.junit.Assert.*;
import org.junit.AfterClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement; public class RuleTest5 {
private static String watchedLog=""; @Rule
public TestWatcher watchman=new TestWatcher(){
@Override
public Statement apply(Statement base,Description description){
return super.apply(base,description);
} @Override
protected void succeeded(Description description) {
watchedLog += description.getDisplayName() + " " + "success!\n";
} @Override
protected void failed(Throwable e, Description description) {
watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName() + "\n";
} @Override
protected void skipped(AssumptionViolatedException e, Description description) {
watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName() + "\n";
} @Override
protected void starting(Description description) {
super.starting(description);
} @Override
protected void finished(Description description) {
super.finished(description);
}
}; @Test
public void fails() {
fail();
} @Test
public void succeeds(){ } @AfterClass
public static void printlog(){
System.out.println(watchedLog);
}
}

测试结果:

succeeds(com.junit.org.RuleTest5) success!
fails(com.junit.org.RuleTest5) AssertionError

在每一条测试执行完之后,分别调用了 succeeded()和failed()方法对 watchedLog进行处理。当然我们还可以在监控方法里做一些其他的事情。

6. TestName Rule

有了这条规则,即使在测试方法内部我们也可以引用方法名。

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

7. Timeout Rule

参考“七 Timeout for tests" 。

8. ExpectedException Rules

参考 ” 四 Exception testing"。

9. ClassRule

@ClassRule 注释扩展了方法级别的规则,它增加了一些静态属性,从而影响整个类。ParentRunner 的任何子类,包括 BlockJUnit4ClassRunner 和 Suite类,都支持 @ClassRule S.

比如说,将ExternalResource 从 @Rule 变成 @ ClassRule,则在整个类里的测试执行过程中它只会执行一次,也就是所有的测试类开始之前会执行 before(),所有的测试类执行结束之后会执行 after()。

import org.junit.ClassRule;
import org.junit.rules.ExternalResource;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class)
@SuiteClasses({RuleTest.class,RuleTest2.class,RuleTest3.class})
public class TestSuite01 { @ClassRule
public static ExternalResource resource= new ExternalResource() {
@Override
protected void before() throws Throwable {
System.out.println("Before Class testing ......");
}; @Override
protected void after() {
System.out.println("After Class testing......");
};
};
}

测试执行结果:

Before Class testing ......
Test Method 1 executing...
Test Method 2 executing...
Test Method 3 executing...
After Class testing......
可以看到,整个过程中ClassRule只执行了一遍。

10 RuleChain

RuleChain 规则允许制定 TestRule的顺序。RuleChain提供一种将多个TestRule串在一起执行的机制,它首先从outChain()方法开始创建一个最外层的TestRule创建的Statement,而后调用round()方法,不断向内层添加TestRule创建的Statement。

public static class UseRuleChain {
@Rule
public TestRule chain= RuleChain
.outerRule(new LoggingRule("outer rule"))
.around(new LoggingRule("middle rule"))
.around(new LoggingRule("inner rule")); @Test
public void example() {
assertTrue(true);
}
}

测试结果:

starting outer rule
starting middle rule
starting inner rule
finished inner rule
finished middle rule
finished outer rule

11 Custom Rules

扩展 ExternalResource 规则可以实现大部分需要个性化定制的规则。如果想要获取更过测试类的信息,则需要实现 TestRule接口。

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement; public class IdentityRule implements TestRule {
@Override
public Statement apply(final Statement base, final Description description) {
return base;
}
}

上面只是一个简单的实现。我们还可以在实现TestRule接口的时候建立自己的构造器、添加测试方法、将提供的Statemetn包装成一个新的Statement。

TestRule的一个实现:

import java.util.logging.Logger;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement; public class TestLogger implements TestRule {
private Logger logger; public Logger getLogger() {
return this.logger;
} @Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
logger = Logger.getLogger(description.getTestClass().getName() + '.' + description.getDisplayName());
try {
base.evaluate();
} finally {
logger = null;
}
}
};
}
}

测试中使用:

import java.util.logging.Logger;
import com.junit.org.TestLogger;
import org.junit.Rule;
import org.junit.Test; public class MyLoggerTest { @Rule
public TestLogger logger = new TestLogger(); @Test
public void checkOutMyLogger() {
final Logger log = logger.getLogger();
log.warning("Your test is showing!");
}
}

测试结果:

二月 03, 2015 4:59:34 下午 com.junit.org.MyLoggerTest checkOutMyLogger
警告: Your test is showing!

Rules的更多相关文章

  1. [Android]使用自定义JUnit Rules、annotations和Resources进行单元测试(翻译)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5795091.html 使用自定义JUnit Rules.ann ...

  2. Favorites of top 10 rules for success

    Dec. 31, 2015 Stayed up to last minute of 2015, 12:00am, watching a few of videos about top 10 rules ...

  3. Yii rules常用规则

    public function rules() {     return array(         //必须填写         array('email, username, password, ...

  4. 【Spring RCP】 RULES规则

    Rich Client 约束规则 1.Constraint 定义了一个约束接口,接口中只有1个方法 public boolean test(Object argument); //这个方法指对约束的检 ...

  5. The Nine Indispensable Rules for HW/SW Debugging 软硬件调试之9条军规

    I read this book in the weekend, and decided to put the book on my nightstand. It's a short and funn ...

  6. Table-3个属性的高级用法(colgroup和 frame和rules)

    之前我用表格的时候基本是caption.thead.tfoot.tbody.tr.th/td,以为是很完整的表格了,原来发现还有colgroup这东东,确实比直接在td里面colspan好用,另外ta ...

  7. YII rules常见规则

    public function rules() {     return array(         //必须填写         array('email, username, password, ...

  8. gcc警告: warning: dereferencing type-punned pointer will break strict-aliasing rules

    Q: 在高优化级别下,不同类型指针之间的强制类型转换可能会触发以下警告: warning: dereferencing type-punned pointer will break strict-al ...

  9. Yii CModel中rules验证 获取错误信息

    在model中定义 public function rules(){ return array( array('Name,Email','required'), array('Email','uniq ...

  10. Yii CModel中rules验证规则[转]

    array( array(‘username’, ‘required’), array(‘username’, ‘length’, ‘min’=>3, ‘max’=>12), array( ...

随机推荐

  1. LENGTH和LENGTHB函数,substrb截取也是同一个道理。

    oracle 利用 LENGTH和LENGTHB函数区分中英文(2009-02-07 10:49:29) 转载▼ 标签: it 分类: oracle 前一段时间,我一朋友问我怎么得出这个字符串是中文还 ...

  2. Struts2默认拦截器配置

    http://blog.csdn.net/axin66ok/article/details/7321430

  3. 增强iOS应用程序性能的提示和技巧(25个)

    转自 http://www.cocoachina.com/newbie/basic/2013/0522/6259.html 在开发iOS应用程序时,让程序具有良好的性能是非常关键的.这也是用户所期望的 ...

  4. Servlet(一)

    BS架构的优势 1.数据库之负责数据库的管理 2.Web服务器负责业务逻辑的处理 3.浏览器提供操作界面 4.不需要单独安装客户端 5.开发相对于CS简单,客户端和服务器的通信模块都是使用标准的HTT ...

  5. SGU 183.Painting the balls

    时间限制:0.25s 空间限制:4M 题意:  在n(n<=10000)个球中,给若干个球涂色,每个球涂色的代价为Ci,使得任意连续m(m<=100)个球中有至少两个球被涂了色. Solu ...

  6. wordpress通过代码禁用IE8, IE9,IE10等IE浏览器兼容视图模式(Compatibility View)

    目前wordpress主流主题大多都放弃了对IE6的支持!甚至IE6,IE7,IE8等的兼容模式也不支持!目前特别是国内的双核浏览器大多数使用使用IE内核都是使用的兼容模式!那将是非常糟糕!如何让IE ...

  7. 泛型? extents super

    ?可以接受任何泛型集合,但是不能编辑集合值.所以一般只在方法参数中用 例子: ? extends Number  则类型只能是Number类的子孙类 ? super String  则类型只能是Str ...

  8. 《作业控制系列》-“linux命令五分钟系列”之十

    本原创文章属于<Linux大棚>博客. 博客地址为http://roclinux.cn. 文章作者为roc 希望您能通过捐款的方式支持Linux大棚博客的运行和发展.请见“关于捐款” == ...

  9. Fedora 18安装Google输入法和云拼音

    由于sunpinyin的词库选词太不准,网友推荐在Fedora 18下使用谷歌拼音及云拼音,于是想要尝试下怎么样.由于fedora 源中谷歌拼音所以选择自行编译,做下记录以备份. #安装fcitx $ ...

  10. Django Admin 简单部署上线

    前言 打算为公司弄一个管理公用密码的平台,由于比较懒,就选择使用Django admin,默认的admin并不漂亮,于是我使用了这个django-suit插件来美化 如图: 是不是比原来的漂亮多了. ...