zoukankan      html  css  js  c++  java
  • 【JUnit4.10来源分析】6 Runner

    org.junit.runner.Runner它是JUnit作业引擎。它在许多类型的支持下的。处理试验和生产(Description)、Failure和Result和其它输出。

    Runner参见图主类层次结构。


    Describable与Runner

    为了保证Runner的子类都有一个Description(虚域模式)数据来源/成员变量,Runner implements Describable

    package org.junit.runner;
    public interface Describable {
    	/**
    	 * @return a {@link Description} showing the tests to be run by the receiver
    	 */
    	public abstract Description getDescription();
    }
    依照凝视可知。runner.getDescription()将返回消息接收者runner将执行的測试的Description/測试树。JUnit中Runner是一个抽象类,

    package org.junit.runner;
    import org.junit.runner.notification.RunNotifier;
    public abstract class Runner implements Describable {	
    	//public abstract Description getDescription();//能够省略
    	public abstract void run(RunNotifier notifier);
    	public int testCount() {
    		return getDescription().testCount();
    	}
    }
    yqj2065不喜欢当中的廉价方法testCount(),或者说我更希望将Runner设计成接口。

    ParentRunner<T>

    排序和过滤临时不讨论。

    <T>

    ParentRunner<T>的取名,意味着本执行器是測试树的某个"parent node" 的执行器。然而对执行器而言,"parent node"仅仅有单元測试类和成组測试类,因而ParentRunner<T>有两个子类型BlockJUnit4ClassRunner和Suite。其它非父结点的Runner。有IgnoredClassRunner、ErrorReportingRunner等。

    ParentRunner<T>的类型參数T。代表其某种孩子的类型。这是一个较别致的设计

    private List<T> fFilteredChildren= null;
    protected abstract List<T> getChildren();

    protected abstract Description describeChild(T child);

    protected abstract void runChild(T child, RunNotifier notifier);

    BlockJUnit4ClassRunner针对一个单元測试类,它没有子执行器。因而此时T为FrameworkMethod

    Suite针对一个成组測试类,它有若干子执行器。T为Runner

    由此可知,执行器相应測试树也是一个树形结构,而一个单元測试类仅拥有一个BlockJUnit4ClassRunner。

    这些抽象方法是ParentRunner<T>最重要的内容。

    Must be overridden


    RunnerScheduler

    该接口表示运行測试方法时的时序调度策略,是顺序运行还是并行。在ParentRunner<T>中默认採用顺序运行。于是我们看见了难得一见的Runnable.run()的直接调用。

    	private RunnerScheduler fScheduler= new RunnerScheduler() {	
    		public void schedule(Runnable childStatement) {
    			childStatement.run();
    		}
    	
    		public void finished() {
    			// do nothing
    		}
    	};
    也能够通过public void setScheduler(RunnerScheduler scheduler)来设置。

    classBlock

    正如【JUnit4.10源码分析】5.2 Rule所介绍的。TestRule声明工厂方法,TestRule的实现类将创建装饰模式中的Statement装饰对象。classBlock(final RunNotifier notifier)代码也创建一个复杂的Statement装饰对象,依照yqj2065的想法,应该将相关代码提取出来。然而。childrenInvoker(notifier)和withClassRules(statement)代码的抽取并不easy。

    	protected Statement classBlock(final RunNotifier notifier) {
    		Statement statement= childrenInvoker(notifier);
    		statement= withBeforeClasses(statement);
    		statement= withAfterClasses(statement);
    		statement= withClassRules(statement);
    		return statement;
    	}

    1.Statement statement= childrenInvoker(notifier);

    给出了ParentRunner的基本操作,我们将private void runChildren(final RunNotifier notifier)内联后,代码为:

        protected Statement childrenInvoker(final RunNotifier notifier) {
            return new Statement() {
                @Override public void evaluate() {
                    for (final T each : getFilteredChildren())
                        fScheduler.schedule(new Runnable() {			
                                public void run() {
                                    ParentRunner.this.runChild(each, notifier);
                                }
                            });
                    fScheduler.finished();
                }
            };
        }
    它的确以匿名类的方式创建Statement装饰对象,然而它与ParentRunner耦合太强,代码中调用了(第4行)getFilteredChildren()、(第5行)依赖域fScheduler、(第6行)调用了待子类提供实现的runChild()。因而能够将它设计成内部类而非一个方法。看起来比較舒服一点。
        protected class ChildrenInvoker extends Statement{
            final RunNotifier notifier;
            ChildrenInvoker(RunNotifier notifier){
                this.notifier =notifier;
            }
    
            @Override public void evaluate() {
                for (final T each : getFilteredChildren())
                    fScheduler.schedule(new Runnable() {			
                            public void run() {
                                ParentRunner.this.runChild(each, notifier);
                            }
                        });
                fScheduler.finished();
            }
        }
    statement= withBeforeClasses(statement);
    statement= withAfterClasses(statement);

    这两部分的代码非常easy放在一个新类中,如同JUnit4.8.2源码分析-5.1 Statement之复合命令演示的那样。


            statement= withClassRules(statement);

    放在一个新类中,须要提供fTestClass和getDescription()两个參数。


    如此这般的折腾,就是体会一下装饰模式在使用中能够出现的各种变体。

    TestRule这样的工厂方法(规则)、或直接的方法形式如JUnit眼下的实现




    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    Nginx 配置对流量、连接和请求的限制
    linux iptables规则介绍
    Javascript 语言精粹 代码片段合集
    Wowza® Media Systems 使用配置手册。
    如何去除My97 DatePicker控件上右键弹出官网的链接
    [转载]jQuery诞生记-原理与机制
    java swing JButton文字显示异常
    c# 内存拷贝 解决json序列化丢失私有数据(二进制序列化反序列化)
    c# Marshal 将字节数组转为结构 封装协议
    c# 串口通信及模拟串口进行调试
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4816635.html
Copyright © 2011-2022 走看看