【JUnit4.10源代码分析】6 Runner
来源:互联网 发布:hotspot实战 知乎 编辑:程序博客网 时间:2024/05/17 22:50
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)代码的抽取并不容易。
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);
这两部分的代码很容易放在一个新类中,如同JUnit4.8.2源代码分析-5.1 Statement之复合命令演示的那样。
statement= withClassRules(statement);
放在一个新类中,需要提供fTestClass和getDescription()两个参数。
- 【JUnit4.10源代码分析】6 Runner
- JUnit4.8.2源代码分析-2 org.junit.runner.Request
- JUnit4 使用指南三 (Runner 特性分析)
- 【JUnit4.10源代码分析】1.2 JUnit4定义的标注大全
- 【JUnit4.10源代码分析】0导航
- 【JUnit4.10源代码分析】5 Statement
- 【JUnit4.10源代码分析】5.2 Rule
- Junit4详解二:Junit4 Runner以及test case执行顺序和源代码理解
- Junit4详解二:Junit4 Runner以及test case执行顺序和源代码理解
- 【JUnit4.10源代码分析】3.4 Description与测试树
- 【JUnit4.10源代码分析】6.1 排序和过滤
- junit4X系列源码--Junit4 Runner以及test case执行顺序和源代码理解
- JUnit4.8.2源代码分析-1 说明
- JUnit4.8.2源代码分析-5 Statement
- JUnit4.8.2源代码分析-3.2 Computer
- JUnit4-Description.java 源代码 解读与分析
- JUnit4-Result.java 源代码 解读与分析
- JUnit4 initializationError[Runner:JUnit4](0.001s)junit4报错
- 台州Acm-搬桌子
- mobile开发中常用的css
- Java中comparable和comparator接口的排序原理
- STM32 ECC校验的一些心得
- Android--ToggleButton控件
- 【JUnit4.10源代码分析】6 Runner
- glew库的使用要点 以及 典型错误(如glewInit无法解析等)
- 在Linux开发环境下, 如何直接查看android数据库sqlite3中的表及数据
- 初识 PS CS6(十五)___分布图层
- 【开发过程问题汇总系列】【iframe自适应高度】兼容 FireFox和IE内核的浏览器
- DirectX纹理渲染原理
- atomic_add_return 函数分析
- Python re模块正则表达式
- hdu 1052 Tian Ji -- The Horse Racing(贪心策略)