
Junit源代码学习.pdf
18页XP 单元测试工具 Junit 源代码学习 谢慧强 xiehuiqiang@ Package framework Class } Class Assert 中比较失败都是抛出 AssertionFailedError Interface Protectable 这个接口是使用了一种比较少见的用法 在 Interface 本身只定义了一个方法 public abstract void protect() throws Throwable; 注意方法 throws 的是所有 Error 和 Exception的祖先通过这种定义可以保 证运行的时候如果出现任何 Error 和 Exception, 都将被抛出而不会导致程序不能 继续运行 Portectable 的接口没有被 framework 包中的任何类实现,它的使用在类 TestResult 中的 run 方法中以下是 run 方法中代码: protected void run(final TestCase test) { startTest(test); Protectable p= new Protectable() { public void protect() throws Throwable { test.runBare(); } }; runProtected(test, p); endTest(test); } 这里实际是声明了一个 Anonymous Classes,实现了 Interface Portectable Interface TestListener TestListener 的用途和它名称一样,用于监听。
主要用于运行时刻监听, BaseRunner(所有运行类,如 TestRunner)实现了这一接口由于运行是通过 TestResult 来实现,只要调用 TestResult.addListener 就可以增加监听,TestResult 会调用接口中相应的方法,具体见 TestResult 主要方法: public addError:增加错误,注意这里错误应该指测试程序本身的错误或者被测试程 序错误,而不是测试失败 addFailure:增加一个测试失败,专用于 AssertionFailedError 的处理 endTest:结束测试 startTest:开始测试 Class TestCase 使用者最主要使用的类,继承 Class Assert,实现 Interface Test主要方法 public TestCase:创建本身,可以指定 TestCase 准备运行的测试方法名称,保存在私 有属性 fName countTestCases:返回 TestCase 数目,直接返回 1 name:deprecated,建议使用 getName,返回 TestCase 当前准备允许的测试方法 的名称(私有属性 fName) run:运行 TestCase,如果没有指定结果存储的TestResult,将调用 createResu (lt 方法。
注意,TestCase 与 TestResult 会有互相调用整个运行流程如下: 1、TestCase.run 调用 TestResult.run 2、TestResult.run 调用 TestResult .StartTest 3、TestResult.run 创建一个 Anonymous 类,实现接口 Portectable 4、在 Portectable. protect 方法中调用 TestCase .runBare 5、通过运行 Portectable.runBare 调用 runBare, 通过 Exception捕获增加错误 及失败报告 runBare:不使用 TestResult 直接运行 runTest:运行测试,注意每调用 runTest 只运行当前 fName 指定的方法 getName:返回 fName setName:设置 fName protected createResult:创建一个 TestResult setUp:在运行 runTest 前调用 tearDown:在运行 runTest 后调用 Class TestFailure 用于存放测试对比失败信息的类。
主要为 Class TestResult 调用主要属性 protected Test fFailedTest; protected Throwable fThrownException; fFailedTest 存放失败的 TestCase 信息,fThrownException存放失败提示信息 主要方法: public TestFailure:初始化,对 fFailedTest、fThrownException赋值 failedTest:返回 fFailedTest thrownException:返回 fThrownException toString: Class TestResult TestResult 用于运行并收集测试结果(通过 Exception 捕获) ,注意 interface TestListener 的所有方法在这里都有同名方法并在同名方法中被调用 主要属性: protected Vector fFailures:测试失败报告保存 protected Vector fErrors:测试错误报告保存 protected Vector fListeners:测试监听器保存 protected int fRunTests:运行的测试 private boolean fStop:是否应该停止测试标志,由 stop 方法设置 主要方法 public TestResult:初试化 addError:synchronized 方法,增加一个错误并向所有监听程序发送错误,调 用 TestListener. addError addFailure:synchronized 方法,增加一个失败并向所有监听程序发送失败,调 用 TestListener. addFailure addListener:synchronized 方法,增加监听程序 removeListener:synchronized 方法,移走监听程序 endTest:结束测试,并通知所有监听程序,调用 TestListener.endTest errorCount:synchronized 方法,返回错误个数 errors:synchronized 方法,用 Enumeration返回所有错误 failureCount:synchronized 方法,返回失败个数 failures:synchronized 方法,用 Enumeration返回所有失败 run:运行测试,创建一个 Anonymous 类,实现接口 Portectable,然后调用 runProtected 方法,可以参看 TestCase 的 run 方法。
runCount:synchronized 方法,返回运行数量 runProtected:实际运行测试 runTests:deprecated 方法,被 runCount 方法替代 shouldStop:synchronized 方法,返回是否应该停止测试 startTest:开始测试,并通知所有监听程序,调用 TestListener. startTest stop: synchronized方法, 设置停止标志 fStop为真 注意是否停止测试TestReuslt 不负责的,stop 只是简单设置停止标志 testErrors:deprecated synchronized 方法,被 errorCount 替代 failureCount:deprecated synchronized 方法,被 testFailures 替代 wasSuccessful:synchronized 方法,如果所有运行过的测试方法都通过,返回 真,否则为否 private cloneListeners:复制 fListeners,主要用于要使用监听列表的 endTest、startTest、 addError、addFailure Class TestSuite TestSuite 用于将多个 TestCase 集合起来放在一起管理,TestSuite 在增加 TestCase的时候实际已经将 TestCase 实例化 (按包括方法多少做多少次实例化) 。
主要属性: private Vector fTests= new Vector(10):存放 TestCase 的实例 private String fName:TestSuite 名称 主要方法: public TestSuite:初始化,可以选择空、指定名称或包括指定的类如果是指定的类, 那么在 TestSuite 初始话的时候,TestCase 已经实例化并加入到 fTests 中 addTest:增加一个 TestCase/TestSuit 的实例到 fTests 中注意由于 TestCase 的 实例化实际上只指定一个测试方法, 即增加一个 TestCase 的实例是注册了其中一 个测试方法,参看 TestCase 类如参数是一个 TestSuite,则相当于增加了一个子 Suite. addTestSuite:增加一个子 Suite,实际效果同参数为 TestSuite 的 addTest countTestCases:返回 Suite(包括子 Suite)中的 TestCase 实例(测试方法)数 量 run:运行测试,注意这里是运行 fTests 中的所有测试,用了 TestResult. shouldStop 方法来判断是否终止运行。
实际是调用了 runTest,逐渐 runTest:运行某一 TestCase 或子 Suite 的测试,注意使用了递归如果参数 test 是一个 TestSuite,会再调用 TestSuite.run testAt:返回 fTests 指定顺序的 TestCase 或者 TestSuite testCount:返回 fTests 大小,注意和 countTestCases 的区别 tests:返回 fTests 的内容 setName:设置名称 getName:增加名称 toString: private addTestMethod:增加一个测试方法(TestCase 实例)到 fTests exceptionToString:返回一个 Throwable 中的提示信息 getConstructor:返回指定类的构造函数 isPublicTestMethod:判断一个方法是否是 public 的测试方法,即一个函数是否 是 public 的,同时是一个测试方法,测试方法参考下面的 isTestMethod isTestMethod:判断一个方法是否是测试方法,既以” test” 为前缀、没有参数及 返回值。
warning: 增加一个错误提示Testcase到fTests中, 注意这里也使用了Anonymous Classwarning 使用主要考虑的往往在对 TestSuite 进行操作的时候,不会因为有 错就终止操作,而是在 run 的时候报告错误 Package extensions Package extensions 主要包括 TestCase 的各种扩展 Class Hierarchy Class TestDecorator TestDecorator 及其子类主要用于在 TestCase 运行前后加入特定操作,进行修 饰不应该使用 TestDecorator 而应该使用 TestDecorator 的子类 主要属性 protected Test fTest。












