严谨而具体地测试

Test Precisely and Concretely

对于测试而言,重要的是代码单元的规定行为,而非特定实施下的附带行为。对于含糊的测试,不应作为接受或报错的借口。测试需要严谨且精确。

尝试、测试、经典测试、常规排序后的事物提供了一种说明实例。对于程序员来说没必要把实现排序算法作为日常任务,但排序是一种常见的概念,大多数人都知道他们能从中得到什么。然而,这种“常见”会导致过去确信的假设变得难以捉摸。

当程序员被问道:“你要测试什么?”,就目前而言最常见的回答是:“一串被排序好的元素序列。”这当然是对的,但也不全对。若要提供更多严谨条件时,很多程序员会要求结果序列和原始序列长度一致。这当然正确,但还不够。例如给出下列序列:

1
3 1 3 1 5 9

下面的序列满足非降序排列且长度与原始序列相同的条件:

1
3 3 3 3 3 3

虽然它满足规则,但绝对不是那个意思!该例子源于真实的产品代码(好在它在发布之前被捕获到了),简单的按键操作或短暂的卡顿便导致了将第一个元素填满给定数组的复杂机制。

完整的后置条件是:结果被排序过,并且是用原始值排列。这才适用于规定行为。结果长度和输入长度一样就没必要重申了。

即使用这种描述方法来规定一个后置条件也不足以给你一份好的测试。一份好的测试还应该可读。它应该易于理解,你能方便地看到它是正确的(或不是)。除非你已经有一份可以检查序列是否被排序、是否包含另一组排列值的代码,否则测试代码很可能比被测代码还复杂。正如Tony Hoare所说:

有两种构建软件设计的方法:其一是将其做得无比简洁以至于明显没有缺陷,其二是将其做得无比复杂以至于没有明显缺陷。

使用具体的实例可以消除这种意外的复杂性并降低意外的概率。例如,给出以下序列:

1
4 1 4 1 5 9

得到以下排序结果:

1
1 1 3 4 5 9

不会再有其它答案了,没有替代品。

具体的实例有助于用一种易于理解且不模糊的方式阐明总体行为。将一个项添加到空集合的结果不是简单地表示它不空了:只是表示该集合有单个项,其持有的项正好是添加的那个单项。两个或更多的项也可悲视为不为空,就会被认为是错的。单个项只是值不同也会被认为是错的。添加一行(数据)到表中不代表这个表就加大了一行,也可以是通过行的键来恢更新行。诸如此类。

在具体的行为中,测试不应简单地做到精准:它们还必须严谨。

0%