1、彻底测试的可能性

  有一种说法是,“测试总是不彻底的”,对于软件整体来说,要做到彻底测试确实很难,但对于局部代码,则是完全可能的。先说 “理想的彻底测试”,对于一段程序,比如一个函数,如果它的所有可能输入都测试过,并且都没有错误,那么可以肯定,这个函数是没有错误的,这是 “理想的彻底测试”。“理想的彻底测试”是做不到的,有没有 “现实的彻底测试”?有!“现实的彻底测试”是所有的等价类都经过测试。

  先说说等价类。“类”是指把输入数据分组,“等价”是指测试效果上的等价,“等价类”是在一组输入数据中,任取一个进行测试,如果测试通过,那么,可以认为同组的其他输入数据也可以测试通过,也是说,测试了一个,等于测试了一组。如果把所有的等价类都找出来进行测试,相当于所有输入都经过测试,这是“现实的彻底测试”。

  对于一段程序来说,“等价类”通常是有限的,因此,从理论上来说,对局部代码进行“现实的彻底测试”是完全可能的。

  2、等价类划分的基本方法

  通常从三个方面考虑程序的输入:正常输入,边界输入,非法输入。

  正常输入:例如字符串的Trim函数,功能是将字符串前后的空格去除,那么正常的输入可以有四类:前面有空格;后面有空格;前后均有空格;前后均无空格。

  边界输入:上例中空字符串可以看作是边界输入,如果输入是一个指针的话,空指针也算是边界输入。再如一个表示年龄的参数,它的有效范围是0-100,那么边界输入有两个:0和100。

  非法输入:非法输入是正常取值范围以外的数据,或使代码不能完成正常功能的输入,如上例中表示年龄的参数,小于0或大于100都是非法输入,再如一个进行文件操作的函数,非法输入可能有:文件不存在;目录不存在;文件正在被其他程序打开;权限错误。

  一般情况下,只要考虑:有哪些正常输入?有哪些边界输入?有哪些非法输入?可以找出大多数等价类,例如,一个函数,功能是把小写金额转换成大写,输入是小写数字,输出是大写金额,那么:

  正常输入有:只有整数,只有小数,既有整数又有小数

  边界输入有:整数部分很大,0.0,小数位数超过两位

  非法输入有:空串,非数字,负数

  “等价类”这个词是从测试的角度来说的,从开发的角度来看,“等价类”与“功能点”具有对应关系,例如,字符串的Trim函数,功能点有:

  如果只有左边有空格,返回删除左边空格后的结果(等价类:左边有空格);

  如果只有右边有空格,返回删除右边空格后的结果(等价类:右边有空格);

  如果两边都有空格,返回删除两边空格后的结果(等价类:两边有空格);

  如果两边都没有空格,返回原串(等价类:两边无空格);

  如果是空串,直接返回(等价类:空串);

  如果是空指针,直接返回(等价类:空指针);

  ……

  一个“等价类”对应程序的一个“功能点”,如果程序的所有功能点都正确实现了,那么这个程序的功能肯定没问题。程序员在写代码时肯定要想清楚程序的主要功能点,否则代码无从写起,因此,如果程序员边编码边测试的话,大部分等价类都是现成的。如果由测试部门做单元测试,测试部门只能依据设计文档来测试,设计文档也会规定程序的功能,要不然无从测起,同样可以说大部分等价类是现成的。

  3、彻底测试的基本思路

  前面说过:如果把所有的等价类都找出来进行测试,相当于所有输入都经过测试,这是“现实的彻底测试”。

  如何把所有的等价类都找出来?根据程序的功能,大部分等价类都是容易想到的,甚至是现成的,但是,如何衡量是否完整?例如,前面所举的两个例子:删除字符串两边空格的函数和将金额小写转大写的程序,我们可以肯定,等价类多也十几个,相当有限,但是,已经列出的等价类是完整的吗?有没有遗漏的?