读书人

[YUAN] JUNIT 源码分析小结

发布时间: 2012-08-08 14:32:45 作者: rapoo

[YUAN] JUNIT 源码分析总结

?今天看了下Junit3的源码,记录下一些心得。

?

?Junit的设计使用了许多设计模式。相关的文章网上也有很多。在TestResult中使用了Collecting Parameters 模式。这个模式的意义在于,该类的有几个成员变量集合,是负责记录测试的Failures和Erros,当然还有总共的Test的数目。

?

TestResult的run TestCase方法会调用具体的TestCase的run方法,如果失败(Failure 或 Error),将通过TestCase生成具体的是败类(TestFailure 或 TestError),最后在TestResult中,集合成员变量把相应的错误再收集起来。

?

这个模式可能比较简单,所以并没有在大话设计模式中看到过。

?

?

Junit3的基本结构可以用下图来表示(网上搜的):

?

[YUAN] JUNIT 源码分析小结

?

这个图有些地方也没有画清楚,Test是个Interface,TestCase 继承了Assert并实现了Test, TestCase同时还引用了TestResult,TestCase的run方法,使用TestResult作为参数,其实调用了TestResult的run方法。 TestResult的run方法通过Test接口又回调了TestCase的runBare方法(包括setUp() 和 tearDown()的运行方法)。

?

再说说TestSuite。TestSuite也实现了Test接口,TestCase可以包括多个Test方法,而TestSuite可以包括多个TestCase,所以TestSuit也可以包含多个Test方法(此处说的Test方法是TestCase里的具体test的方法,不是Test类)。

?

所以TestSuite的使用方法有三种:

?????? 1)指定具体的TestCase对象。

?????? 2)指定具体的TestCase类(所有public的 void,无参数的 test开头的函数会被执行)

?????? 3)指定一个类组,包含多个TestCase类。

?

// 1) TestSuite suite= new TestSuite(); suite.addTest(new MathTest("testAdd")); suite.addTest(new MathTest("testDivideByZero")); // 2) TestSuite suite= new TestSuite(MathTest.class); // 3) Class[] testClasses = { MathTest.class, AnotherTest.class } TestSuite suite= new TestSuite(testClasses);

?

?

?

test方法的特点:

?

???? 在TestSuite中又个isTestMethod()方法,说明了test方法的特点:

???? 1)参数为零个

???? 2)以test开头

???? 3)void返回

?

?? 正是这个特点也使Junit跟testNG比,还需要改进些。

?

?

?

?

设计模式总结:

?

??? 1.命令模式。

??????

?????? Client发出请求,通过Command接口,具体的实现有Executor1,Executor2....ExecutorN,从而实现了Client到ExecutorN的解耦。

?????? 在Junit中,Test是个顶层的接口,TestCase是这个接口的抽象实现。具体的实现由Client决定,你可以写自己的testcase,extends这个TestCase,然后又自己的测试方法,test开头(这是适配器模式)。

?????? 在Junit中Client是Junit框架,例如它通过TestSuite来执行一系列的TestCase时,只要Client实现了TestCase接口,那么Junit框架就能够通过命令模式来调用具体的TestCase了。测试人员也不必关系Junit框架里面是怎么调用的。

?

?

?????2. 适配器模式。

?

????????上面也提到了适配器模式。TestCase是Test的抽象实现类。如果Client实现的TestCase只能执行TestCase中的test方法,那么会产生大量的客户实现类。

?

??????? 一般情况,当Client希望通过发送Request1,Request2,Request3,... RequestN来调用服务器的同一个方法,那么此时服务器端就需要一个Adapter来讲这些RequestN指向同一个具体的实现Adaptee。

?

???????? 在Junit中,框架的执行方法是run(),但是Client具体实现的TestCase可以是以test开头的public,void的方法,方法名随便定义。

?

?

???? 3. 组合模式。

????????

???????? TestSuite可以灵活的组合不同的TestCase,包括三种方式。

?

???? 4. 模板方法模式。

???????

???????? 测试的流程具有可复制性。

?

???? 5. 观察者模式。

?????? ?JUnit提供了三种方式如Text,AWT,Swing这三种运行方式,并且JUnit需要提供方便的扩展接口,这样就存在对象间的依赖关系,当测试进行时的状态发生时(TestCase的执行有错误或者失败等),所有依赖这些状态的对象必须自动更新。

?

???????拿Text运行方式来说。在Junit的textUI包下,有两个类。ResultPrinter和TestRunner类,TestRunner的dorun方法,将resultPrinter加到TestResult的Listener列表中。 当TestCase运行时,会调用TestResult的run方法,TestResult方法的run 又调用不同的Listener的startTest方法,结束时调用endTest方法,出错时,addFailure和addError。就这样实现了观察者动态变化的模型。

?

???? 6. 收集参数模式。

???????? 在TestResult中的run方法,参数是TestCase本身。定义了一个用来抛异常的Protectable对象,这个对象抛不同的exceptoin时,调用不同的add方法,添加Error列表和Failure列表。

?????

?

??? 7. 装饰模式

???????? 在Junit中可以对Test进行扩展,使测试人员能增加自己需要的特殊测试,如重复性测试RepeatTest,在多线程中测试ActiveTestSuite。

???????? 装饰模式又名包装(Wrapper)模式。其意图是“动态地给一个对象添加一些额外的职责”。 装饰模式有几个对象。装饰者,装饰的组件(component),具体的组件,装饰者的具体实现。

??????具体的组件实现了Componet,装饰者拥有组件的引用,用引用来实现这个组件的作用。当需要装饰不同的具体实现时,可以继承装饰者来实现自己的装饰。

????? 在Junit中,Test就是那个Component,它有个具体的组件TestCase,一般的装饰者都是使用TestCase来实现测试。当你需要有自己的特殊需要时,你可能需哟啊一个TestDecorator(Junit帮你实现了)。TestDecorator中,它引用了Test这个组件。例如当你需要重复的测试,你可以写一个RepeatTest来继承TestDecorator,然后传入一个特殊的计数的变量,然后就可是实现自己的功能了。RepeatTest已经被Junit实现了。

?

????????

??????? ??

???????

?

读书人网 >其他相关

热点推荐