JUnit3.81的设计

以上是类图结构,可以先浏览一下有个直观的印象。

1. 功能设计

    要实现的功能很简单,如下

    第一,我写我的测试代码,framework执行我的测试代码,同时framework应该提供回到让我去准备环境和销毁环境。

    第二,在我的测试的代码中,可以检查运行结果,对检查的结果(测试成功/测试失败)framework需要记录。

 

2. 类设计

    2.1 Assert类,在此类中包括各种断言操作。测序代码当检查运行结果时,只需要调用这些方法,他会自动记录检查结果。

    2.1 TestCase类,用户写测试代码时继承的基类. 为了方便将TestCase设计成可以执行多个测试代码(也叫测试用例,英文TestCase,后面统一叫测试用例),而不是只用于一个测试用例。所以在默认情况下TestCase子类中所有public void testXxxx()风格的名字作为一个测试用例对待。在执行一个测试用例是调用setUp()方法去初始化环境,当一个测试用例执行完成后调用tearDown()方法销毁测试环境。

          framework会自动解析TestCase子类中方面签名为public void testXxxx()风格的测试用例,并创建每个测试用例相应的TestCase对象。如果不想framework来完成这个工作你可以添加static suite方法,自己完成这个过程。

          然后framework会对每个TestCase对象依次调用setUp()->public void testXxxx()->tearDown()。如果你想改变对setUp()->public void testXxxx()->tearDown()的调用(runTest方法默认逻辑)可以覆写runTest方法,自己执行测试代码。

          为了检查结果方便,TestCase继承了Assert类,虽然他们不应该不是is a关系

    2.3 TestSuite类,框架的一部分用例存放多个TestCase对象。上面讨论的”自动解析TestCase子类中方面签名为public void testXxxx()风格的测试用例,并创建每个测试用例相应的TestCase对象“就是由该类的构造方法完成(将TestCase子类名作为参数)

    2.4 TestResult 用来存在Assert类断言操作的结果。

    2.5 TestRunner类。运行测试用例的起点,他的描述类类图。

    2.6 Test接口。将TestSuite和TestCase统一到Test接口,出于以下考虑

          其一,出于可扩展性和灵活性考虑,在将来TestSuite中也可以放TestSuite类型的对象,这样需要统一的接口来操作这个两个类。

          其二,还是出于可扩展性和灵活性考虑,给TestRunner一个统一才操作接口,虽然在BaseTestRunner中getTest方法中返回的Test都是TestSuitle。这样TestRunner直接运行TestCase就很容易实现。

 

3. 参数收集模式的使用
    3.1 参数收集模式
        在此模式中,重复的将一个collection (例如list, map.)作为参数传递给一些方法,这些方法向此collection中添加内容。
样例代码:
 String[] userFiles = ...
 List userList = new ArrayList();
 for ( String userFile : userFiles ) {
   addUsersTo(userFile , userList);
 }


 public void addUsersTo(String userFileName, List userList) {
           ...
 }

    3.2 JUnit3.8中此模式的使用
        在JUnit3.8中, 此模式中的collection被包装成TestResult类。在执行测试用例的过程中,framework创建一个TestResult对象,
然后用他作为参数去调用Test的run(TestResult)方法。值得注意的是,在TestCase类中,run(TestResult)方法又调用TestResult的
run(TestCase)方法。
        为什么要这么处理呢?如果不这样那么,需要在下面两个情况之中选择。
        1. 在TestCase代码中需要捕捉断言操作的结果,然后手动添加到TestResult中,例如
        public TestCaseA extends TestCase{
            ...................
            public void testXxxx(){
            try {
             ........
             assertTrue(...);
             ........
            } catch (AssertionFailedError e) {
                testResult.addFailure(test, e);
            } catch (Throwable e)  {
                testResult.addError(test, e);
            }
            ........................ 
        }
            这个情况下对TestCase之类的编写者很不友好。而且为了在testXxx方法内部访问当前TestResult变量也需要作出相应的处理。
也许作为testXxx方法的参数传递进来,也许作为TestCase的property。       
        2. 将“捕捉断言操作的结果,然后手动添加到TestResult”的逻辑即
        try {
            ........
        } catch (AssertionFailedError e) {
             testResult.addFailure(test, e);
        } catch (Throwable e)  {
             testResult.addError(test, e);
        }
           放入断言方法(例如assertTrue)内部。
           这样需要调整所有的assert方法,同样的也要采取相应的方式让assert方法能够访问当前TestResult变量。

           上面两个情况都不是很优雅,我们需要在一个地方统一的捕捉断言操作的结果,然后添加到TestResult中,有了这个地方
还可以做一些类似的事情(例如TestCase执行触发事件)而不至于让逻辑侵入TestCase内部。JUnit3.8将这个地方选择在TestResult
内部,即TestResult的run(TestCase)方法。在这个地方,统一的捕捉断言操作的结果,然后添加到自己内部。
           这样也很优雅的就解决了TestResult变量访问问题。在此方法内部在TestCase执行前后都会触发相应事件。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值