痛定思痛后,Microsoft公司的经理们得出一个结论:如果再不成立独立的测试部门,软件产品不可能达到更高的质量标准。IBM和其它有着成功的软件开发历史的公司便是效法的榜样。但Microsoft公司并不照搬IBM的经验,而是有选择地采用了一些看起来比较先进的方法,如独立的测试小组,自动测试以及为关键性的构件进行代码复查等。Microsoft公司的一位开发部门主管戴夫·穆尔回忆说:“我们清楚不能再让开发部门自己测试了。我们需要有一个单独的小组来设计测试,运行测试,并把测试信息反馈给开发部门。这是一个伟大的转折点。”

  但是有了独立的测试小组后,并不等于万事大吉了。自从Microsoft公司在1984年与1986年之间扩大了测试小组后,开发人员开始“变懒”了。他们把代码扔在一边等着测试,忘了唯有开发人员自己才能阻止错误的发生、防患于未来。此时,Microsoft公司历史上第二次大灾难降临了。原定于1986年7月发行的Mac机的Word 3.0,千呼万唤方于1987年2月问世。这套软件竟然有700多处错误,有的错误可以破坏数据甚至摧毁程序。一下子使Microsoft名声扫地。公司不得不为用户免费提供升级版本,费用超过了100万美元。[Cusumano 1995]

  7.2.2 测试人员的分工

  从Microsoft公司的教训中可知,公司内部对产品的测试(称为α测试),需要开发人员与独立的测试小组共同参与。开发人员应该执行“白盒”测试,即测试源程序的逻辑结构以及实现细节(“白盒”是指看得见程序的内部结构)。而独立测试小组应该执行“黑盒”测试,即按照规格说明来测试程序是否符合要求(“黑盒”是指看不见程序的内部结构)。比如在测试一个模块时,“白盒”测试方法要对模块的所有代码进行单步跟踪测试。而 “黑盒”测试方法只需测试模块的接口是否符合要求,它关心程序的外部表现而不是内部的实现细节。

  小型的软件公司可能没有条件设立独立的测试小组,也有可能测试小组人员不多而忙不过来。这时,可以让开发小组的成员相互测试对方的程序。
  这里要强调的是,α测试不能依赖于开发人员或者测试小组中的任意一方,必须是双方共同参与。“白盒测试”必须由开发者自己执行,因为别的测试人员无法了解到程序的内部实现细节。而“黑盒测试”必须由独立的测试人员执行,因为开发者难以做到客观、公正。开发者在测试自己的程序时存在一些弊病:

  (1)开发者对自己的程序印象深刻,并总以为是正确的(自信是应该的)。倘若在设计时存在理解错误,或因不良的编程习惯而流下隐患,那么他本人很难发现这类错误。

  (2)开发者对程序的功能、接口十分熟悉,他自己几乎不可能因为使用不当而引发错误,这与大众用户的情况不太相似,所以自己测试程序难以具备典型性。

  (3)程序设计有如艺术设计,开发者总是喜欢欣赏程序的成功之处,而不愿看到失败之处。让开发者去做“蓄意破坏”的测试,象杀自己的孩子一样难以接受。即便开发者非常诚实,但“珍爱程序”的心理让他在测试时不知不觉地带入了虚假成份。

  软件产品正式发行前,在公司外部邀请一些用户对产品进行测试,称为β测试。β测试的涉及面广,能反映用户的真实愿望,但花费的时间长,不好控制。一般地,软件公司与β测试人员之间有一种互利的协议。即β测试人员无偿地为软件公司作测试,定期递交测试报告,提出批评与建议。而软件公司将向β测试人员免费赠送或者以很大的优惠价格发行软件的正式版本。

  7.3 测试的主要内容与常用方法

  有一次文学考试,问高尔基是哪国人。一考生乐极而吟:“尔基啊尔基,你若不姓高,我怎知你是中国人。”这是一种瞎猜法。如果这种方法用于软件测试,人累死也测不出什么结果来。

  不论是对软件的模块还是整个系统,总有共同的内容要测试,如正确性测试,容错性测试,性能与效率测试,易用性测试,文档测试等。“白盒测试”是指开发人员从程序内部对上述内容进行测试,而“黑盒测试”是指独立的测试人员从程序外部对上述内容进行测试。很多软件工程教材讲述了各种各样的测试方法并例举了不少示例[Pressman 1997] [Sommerville 1992] [杨文龙 1997]。本节简明地讲述常用的测试方法及其道理。

  7.3.1 正确性测试

  正确性测试又称功能测试,它检查软件的功能是否符合规格说明。由于正确性是软件重要的质量因素,所以其测试也重要。

  基本的方法是构造一些合理输入,检查是否得到期望的输出。这是一种枚举方法。倘若枚举空间是无限的,那可惨了,还不如回家种土豆有盼头。测试人员一定要设法减少枚举的次数,否则没好日子过。关键在于寻找等价区间,因为在等价区间中,只需用任意值测试一次即可。等价区间的概念可表述如下:

  记(A, B)是命题f(x) 的一个等价区间,在(A, B)中任意取x1进行测试。

  如果f (x1) 错误,那么f (x) 在整个(A, B)区间都将出错。

  如果f (x1) 正确,那么f (x) 在整个(A, B)区间都将正确。

  上述测试方法称为等价测试,来源于人们的直觉与经验,可令测试事半功倍。

  还有一种有效的测试方法是边界值测试。即采用定义域或者等价区间的边界值进行测试。因为程序员容易疏忽边界情况,程序也“喜欢”在边界值处出错。

  例如测试 的一段程序。凭直觉等价区间应是(0, 1)和(1, +∞)。可取x=0.5以及x=2.0进行等价测试。再取 x=0以及x=1进行边界值测试。

  有一些复杂的程序,我们难以凭直觉与经验找到等价区间和边界值,这时枚举测试相当有难度。

  在用“白盒测试”方式进行正确性测试时,有个额外的好处:如果测试发现了错误,测试者(开发人员)马上能修改错误。越早改正错误,付出的代价越低。所以大多数软件公司要求程序员在写完程序时,马上执行基于单步跟踪的“白盒测试”。

  7.3.2 容错性测试

  容错性测试是检查软件在异常条件下的行为。容错性好的软件能确保系统不发生无法意料的事故。

  比较温柔的容错性测试通常构造一些不合理的输入来引诱软件出错,例如:

  (1)输入错误的数据类型,如“猴”年“马”月。

  (2)输入定义域之外的数值,上海人常说的“十三点”也算一种。
  粗暴一些的容错性测试俗称“大猩猩”测试,除了不能拳打脚踢嘴咬,什么招术都可以使出来。这里我举不出例子,因为我没有对程序粗暴过,并且这辈子也不打算学会粗暴。