软件测试的目标:失败等于成功最近,我的一个同事在走廊里拦住我,非常骄傲和热情地给我描述了她为一套自动测试程序进行的设计和采用的技术。她说:“最妙的是他们都能够非常顺利、漂亮的运行”。在我走开的时候我在想怎样采取最温和的方式告诉她,她已经“迷失了方向”。虽然她尽了很大的努力去建立一套成功的测试,但是她没有认清软件测试的真正目的。软件测试的真正目标是什么?为了研究这个问题,我随机问了一些软件开发和测试工程师、管理人员。其中一些说目标是验证软件是否满足用户和产品的需求。其他的人给出了更简单的回答,例如:“确认软件没有Bugs”以及“为了验证软件能够正常运转”。就我看来,这些说法都不准确。简单来说,软件测试的真正目的是找到以前没有发现的bug。下面我将从我对软件测试目标的看法出发,剖析我同事关于软件测试的主要目标的误解,并给测试人员一些建议。误解1:软件测试的目的是为了确保没有Bug这种看法反映了一种对于软件本质的乐观但从根本上错误的观点。一个简单的事实就是不存在“bug-free”的软件。为什么是这样呢?首先,在等式的开发一边,你必须面对时刻在变化的技术,一个复杂的而且经常有缺陷的应用设计,集成新的已存在的系统带来的困难,等等。人本身的错误也是一个很大的因素。虽然现代思维应用开发工具可以自动生成代码,但是在有些地方人必须参与到开发过程中,而人是会犯错误的。而在等式的测试这一边,不可能让你的产品在送到你的用户以前运行所有可能的测试来检测出每一个可能的bug。让我们来看一个简单的假定的例子。比如说你要测试一个这样的程序:接受3个整型的数值作为输入,每一个数值的范围在0到9之间。在种操作系统下运行。可以访问存储在3个不同厂商中任何一个提供的数据库中的数据。我们计算一下,我们有1,000种可能的排列作为测试输入。为了测试在每个操作系统上的每种排列,我们需要2,000个测试用例,另外再考虑到每种输入在每个支持的数据库运行一遍,我们需要6,000个测试用例。这个数字还没有考虑到其他的测试情况,例如网络故障,磁盘空间不足以及内存耗尽等等。所以实际上我们需要测试用例的数目要更大一些。无疑,我们不得不接受这样一个事实:我们只能生活在一个所有的软件都有bug的世界当中。然而,我们没有必要绝望。经过精心的计划,我们可以选择性地找出产品中最多出现危险以及对我们的用户最重要的部分中的bug。下面是我发现的有效的一些步骤。在你的计划当中加入风险分析正确理解你的客户需求文档本身就是一门科学(后面将会详细讲到)。如果你不能直接接触到你的用户--例如,通过客户焦点小组,那么你就应该和你的客户支持部门一起商讨你的测试计划,因为他们直接接触到最终用户。要明白你的产品哪些部分处于危险当中同样需要分析。变更是危险的主要来源;如果你引入了一个变更,你可能不注意地引入了一个新的bug或者发现一个已经存在的bug。因此,支持新功能的代码一直是一个寻找危险的好地方。为了修正一个bug而修改的代码也是这样。而且,如果你在某个地方发现了bug,那么在附近潜藏着其他bug的可能性就很大。虽然你可能认为经过多年修正了很多bug的地方最后“清除干净了”,这种想法只是在修正时发现了bug的根源的情况下才是正确的。如果bug的根源是糟糕的设计,而进行的修正只是一个简单的补丁而不是从根本上解决这个问题,那么这个修正实际上可能引入了新的bug。另外,记住:即使是基于“根本原因”的修正也有可能会引发基础性变更,暴露其他严重bug。理解产品是如何工作的--和为何可能出故障对一些测试者来说,第一个想做的就是看产品外在的可见的“行为”--将精力集中在他们的产品客户将看到的部分。这样做效力有限,因为他们没有清楚的理解产品程序的逻辑,数据流等等,这些是用户不可见的。为了能够理解产品是如何工作的,以及怎样会出故障,你必须看“罩子下面”并且在你的测试中用到你看到的东西。例如,如果你只看一个GUI,你可能看到程序通过一个格式化的HTML表格显示一个特定的数据库查询的结果。然而,除非你知道这个表格的表示是一个Java数组对象,从服务器传到客户端,然后转化为一个HTML表格,否则你就不会知道这里存在一个潜在的一个客户端性能瓶颈的危险。如果一个用户运行一个查询,返回的记录太多,就会导致客户端在处理表格的时候像死机一样。(我在几年前是通过这样的方法解决这个问题的:每次让客户端只接收一部分结果数据,并且明确地告诉用户还有其他的数据未传过来。)