首页 > 代码库 > 【JUnit4.10源代码分析】6 Runner

【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>

排序和过滤暂时不讨论。

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。

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)来设置。



【JUnit4.10源代码分析】6 Runner