二、     白盒测试
另一种常用的测试方法是白盒测试法,也称为逻辑驱动测试,它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,检验程序中的每条通路是否都能按预定要求正确工作。
这一方法是把测试对象看作一个打开的盒子,将程序中的每条语句至少执行一次,用以证明该程序对输入数据做出了正确的应答,但这是远远不够的。在这里不会对这个问题进行冗长的阐述,这部分内容将会在第四章中详细说明。在本章中将介绍一些我们都会想到使用的方法比如穷举测试法,也就是说,在执行完所有的测试用例后,数据将遍历程序的所有逻辑路径,对程序进行了完整的路径测试。
可是这种方式仍然存在缺陷,因为程序中的逻辑路径数有可能是个天文数字。看到这里,先让我们思考一下图2.1所示的一个小程序的控制流程,图中的点和圆圈表示语句的执行节点或者分支语句的终点。该图描述了语句1020之间执行了20DO LOOP循环,在这个循环中还包含嵌套的IF语句。逻辑路径数与从a点至b点所经过的路径数相同(假设程序中所有路径彼此独立),这将会有大概104个或者说是100万亿个路径,也就是从51520的累加和,其中5代表循环体的数量。因为大多数人很难直观的理解这个数字的含义,那么让我们换一种方式来思考:如果每一个用例从写入数据至执行结束需要用五分钟的时间,那么遍历每一条路径将会用去大概一亿年的时间。如果你可以比上述的执行时间快上300秒,假设对每一条路径测试需要1秒的时间,将这项工作做完也需要3200年。
当然,实程序的每个执行结果不是互相独立的,这意味着执行路径可能会少一些。另一方面,在现实中需要测试的程序的规模要远远大于图2.1所示的小程序。因此,尽管看似穷举测试法能够检测出程序的所有执行路径,但测试的工作量过大,需要的时间过长,实施起来仍是不现实的。
接下来将阐述这种测试方法的第二个缺点“穷举路径测试意味着完整测试”,因为即使对程序中的每条路径都进行了测试,程序仍可能有问题存在。下面将从三个方面来详细说明。
第一点,穷举测试不能保证程序完全符合需求规格说明书的规定。例如,要求你来写一个按递增顺序进行存储的程序,但实际上却写成了按递减顺序存储,这时候进行穷举测试就没有意义了,程序仍然存在BUG,因为它不符合需求说明书的要求。
第二点,程序不正确的原因可能是因为它缺少执行路径。穷举测试当然不会检测出它是否缺少必要的执行路径。
第三点,穷举测试很可能发现不了程序的数据敏感错误。有很多这样的例子,但一个简单的例子就足以说明问题。假设你想在程序中比较两个数的大小,进一步说,就是检测这两个数的差是否小于预定值。也许你会写下面的JAVA语句来实现
if (a-b < c)
System.out.println("a-b < c");
当然,这段程序的声名中存在错误,因为它应该进行Ca-b的绝对值的比较。能否发现这个问题取决取于输入数据ab的值,仅仅通过执行程序的每一条路径是不能发现这个问题的。
结论,尽管穷举测试能够对所有的输入条件进行测试,但事实证明它检测不到程序的所有问题而且是不可行的。或许会有一种测试方法是能够将黑盒测试与白盒测试的相结合,这个问题将会在第四章进一步阐述。