JUnit下的模式运用

参见原文:http://junit.sourceforge.net/doc/cookstour/cookstour.htm

我在这里写一点学习心得,这篇不是翻译。
JUnit是一个设计良好的测试框架,学习的过程让我再次感受到模式所带来的好处。

 

Command

JUnit适合给开发人员做单元测试(白盒子),这也是JUnit的目标。一个单元测试用例可以代表一个测试步骤,具有原子性的特点。在开发过程中,我们常常把这样的用例封装成一个类,实例化后就代表了一个单元实体。这样做的好处就是让一个测试用例独立出来而不受其他逻辑干扰(我发现这样的想法在现实生活中也是非常合理的)。
Command模式很好的解决了这个问题。对于一个测试用例来说,它可以看成是一个执行体(说白了就是做事步骤)。Command建议将这样具有多个而类似的执行体封装执行类,并遵守一定的规范(Interface)。看下图:

command

java 代码
  1. public abstract class TestCase implements Test {    
  2.     private final String fName;    
  3.   
  4.     public TestCase(String name) {    
  5.         fName= name;    
  6.     }    
  7.   
  8.     public abstract void run();    
  9.         …    
  10. }  

TestCase代表一个Command模板,它被设计成abstract,需要在实际运用中继承它,实现run()。

 

Template Mothod

有了TestCase还不行,从源码来看,执行测试的逻辑交给run()是远远不够的,因为实际情况复杂的多。在实践过程中,我认为这样一个测试用例是比较合理的:建立一个测试对象->测试它->清除这个测试对象。这三个步骤应该是连续的(它应该理解为一个测试用例而不是三个)。对大多数测试来说这个用例模板是适用的(哦,终于可以用模板这个词了)。
扯了半天终于可以把Template Method模式带出来了,先来看看它的简介:
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
Template Method
在这个模式中,run()定义了算法(如下面代码),而具体的算法实现则交给子类处理。这样做的好处是,你在写测试用例的时候不必再关注框架的算法了,只需要关注测试内容。

java 代码
  1. public void run() {    
  2.     setUp();    
  3.     runTest();    
  4.     tearDown();    
  5. }   
  6.   
  7. protected abstract void setUp();   
  8. protected abstract void runTest();   
  9. protected abstract void tearDown();  

 

 

Collecting Parameter

 Collecting Parameter不是GoF所涉及的模式类型。它的作用呢,还是先看看原文好了:
It suggests that when you need to collect results over several methods, you should add a parameter to the method and pass an object that will collect the results for you.
为了收集测试结果(别告诉我不需要啊),定义一个收集器当作参数传给run(),看看源码:

java 代码
  1. public void run(TestResult result) {    
  2.     result.startTest(this);    
  3.     setUp();    
  4.     try {    
  5.         runTest();    
  6.     }    
  7.     catch (AssertionFailedError e) { //1    
  8.         result.addFailure(this, e);    
  9.     }    
  10.   
  11.     catch (Throwable e) { // 2    
  12.         result.addError(this, e);    
  13.     }    
  14.     finally {    
  15.         tearDown();    
  16.     }    
  17. }  


Collecting Parameter
TestResult就充当一个测试结果收集器。
我觉得这样做有如下一些好处:

  • 隐藏了测试收集的逻辑:对于开发者来说,测试逻辑才是主题。
  • 如果TestResult设计成单例,则能将测试结果集中处理,最大限度的重用代码。

 (忙活了两天,差点忘了。今天是圣诞)

 Adapter And Pluggable Selector

回到先前的Command模式。每个Command代表一个TestCase类,而实际情况是,每个TestCase会有多个测试方法(想象一下,如果一些测试方法使用的是同一个测试对象,那么些多个TestCase就显得很浪费了)。测试的某一时间段内,我们只用一个测试方法。JUnit提供了两个模式来实现--Adapter And Pluggable Selector(我一直觉得这两个方法差不多)。下面介绍Pluggable Selector,Pluggable Selector就是在实例化的时候给定一个参数,比如某个测试方法的字符串名称,这样在实例化TestCase的时候就知道要运行什么测试方法了(用反射就能做到)。看代码

java 代码
  1. public simpleTest(String testMethodName)   
  2. {   
  3.      fName = testMethodName;   
  4. }   
  5.   
  6. protected void runTest() throws Throwable {    
  7.     Method runMethod= null;    
  8.     try {    
  9.         runMethod= getClass().getMethod(fName, new Class[0]);    
  10.     } catch (NoSuchMethodException e) {    
  11.         assertTrue("Method \""+fName+"\" not found"false);    
  12.     }    
  13.     try {    
  14.         runMethod.invoke(thisnew Class[0]);    
  15.     }    
  16.     // catch InvocationTargetException and IllegalAccessException    
  17. }  

这个模式跟Adapter非常的相似。每次测试的时候,只要指定参数,就能实例化出不同特性的TestCase。
Pluggable Selector

 

Composite

下面就该看到有多个TestCase的情况了。对于这种情况,使用者希望有跟TestCase一致的处理方式。该Composite登场啦。比较简单,就不啰嗦了。
Composite

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值