技术开发 频道

一种新的单元测试的方法

  1、通过接口和约束来设计Design by interface and contracts

  软件设计中著名的词语说“Design by interface”,仍然在我耳边响起。因此你也当然可以“Test interface”。

  很多正式的“Design by interface”意味着定义好你的接口,并且接着实现它们(可能大部分时间是由不同的人或者公司来实现)。总之,你能够影响到的只是如一个强类型语言,例如java能为你提供的那样:一个接口的实现必须遵循接口的签名,类型和参数变量保持一致。你不能控制到那些具体的行为。当然,这也是一个API设计上的一个很大的局限性,因为可能导致实现完全不可预期的行为。

  这里我就引出Eiffell language 和他的 design by contract (DbC)方法,约定来引导继承过来的特征的重新定义。在java中有很多工具支持Dbc,但是我的想法是我们已经有一个很强大的方式来测试方法上的约束,并且使用更少的代码来清楚行为:Unit Tests单元测试。

  使用TestedBy,测试在接口(或者父类)上声明,所有实现类都能运行这些测试,来验证这些实现类的行为,是符合父类类型上的行为和约束定义的。API设计者不仅提供接口,也提供一套验证该接口行为的测试类。因此每个实现者需要提供他们自己的实现,并且运行API设计者提供的测试,来保证实现类不仅是类型安全的,也是行为安全的。TestedBy传递给测试类一个被测试接口的实体类,并调用接口定义好的测试。

  这是一个使用TestedBy的例子:我们已经添加了@TestedBy注释在API接口,并提供一个@BeforeTestedBy注释来提供一个接口的实例。TestedBy将在实现类APIImplOne和APIImplTwo上运行shouldAddTwoAndThree,测试在第一个类上成功而在第二个类上失败。

  Java代码

1. public interface APIInterface {

  
2. @TestedBy( testClass = "it.javalinux.testedby.APITest", testMethod = "shouldAddTwoAndThree" )

  
3. public int add(int a, int b);

  
4. }

  
5.

  
6. public class APIImplOne {

  
7. public int add(int a, int b) {

  
8. return a + b;

  
9. }

  
10.

  
11. public class APIImplTwo {

  
12. public int add(int a, int b) {

  
13. return a - b;

  
14. }

  
15.

  
16. public class APITest {

  
17.

  
18. private APIInterface instance;

  
19.

  
20. @BeforeTestedBy

  
21. public beforeTestedBy(APIInterface instance) {

  
22. this.instance = instance;

  
23. }

  
24.

  
25. public void shouldAddTwoAndThree() {

  
26. assertThat(instance.add(3,2), is(5));

  
27. }

  
28.

  
29. }

   当然,我使例子尽量简单,但是TestedBy有更多的注释,比如当没有参数的构造函数的简单反射调用时,被测试类的实例工厂能被指定,这些注释还远远不够。

0
相关文章