JUnit 4.7学习笔记(二)——BlockJUnit4ClassRunner分析

前面提到过Junit的核心之一就是Runner,它是具体跑测试用例的人。自然我们就要先分析这个东西。通过Runner的层级视图我发现了不少新东西。不过我知道4.1版本的Runner核心就是org.junit.internal.runners.JUnit4ClassRunner这个类,所以我就先进去看看它的变化。结果发现它已经被deprecated了。而现在4.7取而代之的是我们上一次提到过的org.junit.runners.BlockJUnit4ClassRunner。

看一下这个类的层级图:
[img]http://dl.iteye.com/upload/attachment/181867/d985fa1b-fab1-3e51-b8f5-d445c4b38535.jpg[/img]
会发现它上面还有一个叫ParentRunner的东西,Runner接口的Run方法就是这个类实现的。

来看看这个Run方法:

@Override
public void run(final RunNotifier notifier) {
EachTestNotifier testNotifier= new EachTestNotifier(notifier,getDescription());
try {
Statement statement= classBlock(notifier);
statement.evaluate();
} catch (AssumptionViolatedException e) {
testNotifier.fireTestIgnored();
} catch (StoppedByUserException e) {
throw e;
} catch (Throwable e) {
testNotifier.addFailure(e);
}
}

发现它所有的测试,现在是通过Statement类来调用的。看看classBlock(notifier)这个方法:

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


这个Statement会把一个测试会执行的所有方法都封装起来。其中从childrenInvoker这个方法命名来看,这次我们的junit会支持树级结构的测试哦,所以才会诞生了这次的ParentRunner。

来看看childrenInvoker方法及里面涉及到的一个runChildren:

protected Statement childrenInvoker(final RunNotifier notifier) {
return new Statement() {
@Override
public void evaluate() {
runChildren(notifier);
}
};
}

private void runChildren(final RunNotifier notifier) {
for (final T each : getFilteredChildren())
fScheduler.schedule(new Runnable() {
public void run() {
ParentRunner.this.runChild(each, notifier);
}
});
fScheduler.finished();
}


然后这个runChild(each,notifier)方法是由BlockJUnit4ClassRunner实现的:

@Override
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
//每个测试运行时会往里面添加测试结果,后期这些结果会汇总然后显示出来
EachTestNotifier eachNotifier= makeNotifier(method, notifier);
//如果发现测试方法上面带有@Ignore注解,就忽略这个测试方法
if (method.getAnnotation(Ignore.class) != null) {
eachNotifier.fireTestIgnored();
return;
}

//通知测试引擎开始测试
eachNotifier.fireTestStarted();
try {
//执行方法
methodBlock(method).evaluate();
} catch (AssumptionViolatedException e) {
eachNotifier.addFailedAssumption(e);
} catch (Throwable e) {
eachNotifier.addFailure(e);
} finally {
//通知引擎测试已经完成
eachNotifier.fireTestFinished();
}
}


看看methodBlock:

protected Statement methodBlock(FrameworkMethod method) {
Object test;
try {
test= new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return createTest(); //这个方法只会去初始化只有一个构造函数的类!
}
}.run(); //进行测试实体的初始化
} catch (Throwable e) {
return new Fail(e);
}

//测试结果封装为InvokeMethod
Statement statement= methodInvoker(method, test);
//如果有@expected的话,封装为ExpectException
statement= possiblyExpectingExceptions(method, test, statement);
//如果有@timeout的话,封装为FailOnTimeout
statement= withPotentialTimeout(method, test, statement);
//如果测试中带有有@Rule注解的字段,没有一个规则就会进行一次特定的监控
statement= withRules(method, test, statement);
//如果测试类带有@Before注解,封装为RunBefores
statement= withBefores(method, test, statement);
//如果测试类带有@After注解,封装为RunAfters
statement= withAfters(method, test, statement);
//返回结果
return statement;
}

我发现除了传统的方法调用记过,ExpectException结果,RunBefores结果和RunAfters结果这些Statement对象外,还添加了Timeout和Rules的描述。Timeout就直接忽略了,这么简单应该大家都可以不言而喻,下面来重点研究一下这个前所未见的MethodRule规则。

明天继续,要去干其它事情了。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值