zoukankan      html  css  js  c++  java
  • Rules

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

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

    http://img.blog.csdn.net/20150203170643336

    基本的规则有:

    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!"));  
        }  
    }  

    运行结果:

    http://img.blog.csdn.net/20150203141015379

    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!
    "; 
    } 
    
    @Override 
    protected void failed(Throwable e, Description description) { 
    watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName() + "
    "; 
    } 
    
    @Override 
    protected void skipped(AssumptionViolatedException e, Description description) { 
    watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName() + "
    "; 
    } 
    
    @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!

  • 相关阅读:
    java学习day2--java和javac命令的使用
    java学习day1--了解java及JDK环境变量的配置
    idea 修改console 日志区的背景
    微信的storage的操作
    python 基础
    shiro标签说明
    IDEA 修改编辑区的背景颜色
    java注解
    java的反射
    创建一个maven项目
  • 原文地址:https://www.cnblogs.com/miniren/p/4638483.html
Copyright © 2011-2022 走看看