来自http://junit.sourceforge.net/doc/cookstour/Image6.gif
1.在这个composite模式之中,TestSuite与它的接口Test的聚合关系。这种关系完美的满足了客户代码自由自在的组装自己的测试用例结构。称为面对对象的递归组合。现在TestCase和TestSuite都具有良好的扩充性。
2.TestResult:如何进行职责的分配永远是对象的话题。TestCase直接面对符合测试框架规范的测试用例的每一个方法,每一个方法都会致使一个TestCase的对象构造出来,这样测试用例的方法之间就很好的隔离;每一个TestCase都是一个独立的测试单元,TestCase正是保证这种自主性。测试用例运行中的信息收集和信息积累。用例和信息积累都是潜在可能各自发生变化的,区别用例的执行和信息的收集就可以得到更多的灵活性和潜在复用性。用例和信息积累各自都又具有很好的通用性。TestResult正是测试执行信息积累而被封装的类(Test提供了信息积累的收集点:countTestCases),可以看到TestResult是作为访问者(Visitor)注册到Test中去的。对于测试执行信息的处理,向TestResult注册了estListener的Observer模式。
3.在TestResult通过接口Protectable将执行信息的处理优美的隔离到一个单独的方法中来:
public interface Protectable {
/**
- Run the the following method protected.
*/
public abstract void protect() throws Throwable;
}
在TestResult中:
/**
Runs a TestCase.
*/
protected void run(final TestCase test) {
startTest(test);
Protectable p= new Protectable() {
public void protect() throws Throwable {
test.runBare();
}
};
runProtected(test, p);endTest(test);
}/**
- Runs a TestCase.
*/
public void runProtected(final Test test, Protectable p) {
try {
p.protect();
}
catch (AssertionFailedError e) {
addFailure(test, e);
}
catch (ThreadDeath e) { // don’t catch ThreadDeath by accident
throw e;
}
catch (Throwable e) {
addError(test, e);
}
}
整个JUnit框架是功能完美而且精巧的。其中的核心代码也不过千余行而已,处处都能感觉到灵活和可扩充。