作为芸芸众程序员的一员,我对软件开发中的一切都充满问题。是关于测试,作为一名唯物主义者,我相信众物都有其神,于是我找到了测试之神。

我问:神仙,为什么我们需要测试?

大神用怜悯的眼神看着我,说到:我可怜的孩子,之所以需要测试,都是上帝的错啊,上帝创造了你们,但是因为没有测试,所以你们都是不完美的、不理智的,你们会被情绪、环境左右,会犯错。

大神说这话的时候充满了怜悯,当然,他对任何事情都充满怜悯。我想,我该叫他怜悯之神。

我说:哦,这么说上帝也是不完美的,因为他也需要测试?

怜悯之神果然是神仙:咳咳,说到哪儿了,你吃饭了吗?

我问:我们需要测试,可是,为什么我看测试人员只是天天敲键盘而已啊?

怜悯之神说:你敲键盘是在写代码,测试人员敲键盘是在获取当前系统的信息,这两者真正的工作都是那些脑力活动,是在敲击键盘这个物理行为之前以及伴随这些物理行为的脑力活动。如果你敲击键盘的时候没有进行思考,那么你不是在进行开发和测试;而且,如果你在思考但是没有敲击键盘,你还是可能在进行开发和测试。

我说:关键是思考。

怜悯之神说:是的。他显然对后半句犹豫了一下,但是还是说了,人类一思考,我们发笑。

我想,一点都不好笑,连朝鲜都一比零小胜巴西了。我说,其实对软件开发人员来说,我们也应该通过使用自己的产品来对它进行测试。

怜悯之神点点头,说,这叫做“吃自己的狗食”,如果你都对自己的产品感到担心和鄙夷,别人为什么要买它?

我说,可是,除非我们开发的是开发工具,否则我们根本不可能用它。地球人都知道,做减肥药广告的从来不喝减肥药,买火腿肠的从来不吃火腿肠....人人都需要是化学家。

怜悯之神说:所以完全由开发人员构成的测试样本不太可能代表整个用户群。

我自言自语道,所以我们需要测试人员,需要另一个角度的思考。

我问:尽管测试人员测试了,但是为什么系统还是存在缺陷哩,难道他们不对所有可能性都进行测试的吗?

怜悯之神翻了我一个白眼,叹了口气。作为报复,在下面的叙述中,我将称他为白眼之神。

白眼之神说,对任何程序而言,可能进行的测试数据都是无限的。测试也许可以令人信服的表明存在缺陷,但是永远无法表明不存在缺陷。

我想了想,说,我们现在的系统需要导入客户的遗留数据,光报表多达20万,如果一张张的校验报表内容和样式,那么一定会死人的。

白眼之神说,那你们是怎样测试的哩?

我说,抽取样本测试哈。我说,我明白了,由于我们无法测试所有的可能性,那么任何测试实际上都是某种程度的样本测试,这些样本以某种方式代表整个可能测试集合的一个部分或者片段。

白眼之神点点头,说,测试只是采样!

我说,正像我们去医院体检,所有化验单上都写着,本结果只对该样本负责。

白眼之神说,实际上,采样也是一个心理过程,而且是一个感性过程,令某人满意的样本也许会让另外一个觉得一点都不满意。

我说,由于不可能进行穷举测试,所以我们往往在两个目标间徘徊:希望测试能够覆盖所有令人感兴趣的条件,希望测试集减少到可以管理和承受的程度。像吃自助餐,希望吃到所有东西,但是又要不把肚皮撑破。

白眼之神说,所以我们需要尽可能选择那些具有强代表性的样本进行测试,而这是测试人员的优势。另外,多样化样本发现的问题可能超过大样本发现的问题,同样,测试团队多样化也可能发现更多的问题。

我说,是的,同样是抽血,一些人会要求早上不吃饭抽取静脉血,一些人则需要间隔取几次血。

我问:开发中,我们采用了TDD的方式,我们单元功能测试的覆盖率也很不错,这样,我想我们可以减少测试人员?减少系统测试?

神说,你会因为一架飞机保证它所有的部件在组装前都进行了测试而乘坐它的处女航吗?

我说,哦,罗老号发射失败了。

神说,但是,良好的单元功能测试能够为系统测试去除噪音。

我说,缺陷都不是自己钻进去的,而是开发人员放前去的。单元功能测试能够在一定程度上阻挡开发过程中缺陷的进入,同时阻挡一些简单的缺陷,系统测试不能捕获所有缺陷,相对单元功能测试,系统测试会花费更长的时间和成本,这些时间和成本能够通过单元功能测试得到部分节约。

神说,开发人员的测试保证了他对需求的理解和实现的一致,但是开发人员对需求的理解和真正的需求一定一致吗?

我说,所以需要测试人员即时验收。

神说,另外,关于TDD,从心理学的角度说,一个人是很难发现自己的错误的,所以TDD和结对编程一起实践会有比较好的效果。

我问:为什么很多项目后的集成测试阶段会那么长哩?这总是导致我们的项目延期,而几乎所有的项目都会延期。

神说,说说你们的集成测试阶段都在做些什么?

我说,噢,我们拉出一个发布分支,冻结代码提交,开始进行测试,找出缺陷,查明缺陷原因,根据重要性修改缺陷,然后重新测试,以此循环。恩,问题在于此时总会发现大量缺陷,并且我们每修复一些缺陷总会引入新的缺陷,所以这个时间拉得很长。

神说,修复缺陷的同时引入新缺陷,这叫做故障反馈率(FFR),也是一个修复让系统中产生了另一个缺陷的情况所占的百分比。这个数值如果在50%以下很幸福了,另外,压力和试图提高缺陷修复速度都会提高FFR。

我说,也是修复缺陷的同时引入新缺陷是个正常情况。恩,可是我的问题是为什么后的测试阶段需要花费这么长时间?

神说,难道你不觉得是你们经理错误的估计了后集成测试阶段所应该花费的时间?

我说,噢!

神说,此外,测试不等于除错。

我想了想,说,是的,说的是后集成测试阶段,但实际上包含了两个行为:测试和除错,相比测试,除错占据了更多时间。恩,我们现在的一个项目特性,由于开发时没有考虑性能问题,导致上线前花费了大量时间进行调优。

神说,项目延期的主要问题在于测试推迟。

我说,是的,这个给我的印象很深,如果在开发阶段进行大数据的测试,那么会节省很多时间。一个缺陷,发现的越晚,修复的成本越高。

神说,要测试先行,并且测试往往在项目开始开发前都已经开始了,测试需要贯穿于整个开发过程,频繁进行,而是不推迟到后的集成测试阶段。TDD和持续集成是很不错的实践,但是它们仅仅是测试中的一部分。

我说,那么,测试保证了质量。

神说,三鹿没有测试吗?

我说,....

神说,测试只是提供信息。至于这些信息的定义、重要性以及所要采取的反应都取决于人,而人做出的决定都是感性的,利益驱动的。

神说,如果开发的产品本身质量低劣,进行测试你不觉得是浪费大家的时间吗?对低劣的代码测试得再好又有什么用呢?一段时间发现的缺陷越多,并不意味着剩下的缺陷越少,而总是意味着会出现更多的缺陷。

我说,我明白了,测试只是收集信息,除此之外,并不能做其他任何事情。正如我们去体检,体检报告只能反映出当时我们的身体状态,至于健不健康,则取决于我们平时的生活习惯,这是两个分开的事情,体检并不保证我的健康。

神说,很多大公司非常看重测试部门,原因其实是他们无法看清楚他们自己的开发过程,于是只能从测试里获取信息,而这些信息对整个软件开发来说只是一部分而已。我看到过有项目经理向测试人员询问是否可以交付,这根本上是在推卸责任,信息和作出决定根本是两回事,更何况测试收集的信息只是部分信息呢,如果是这样,不如让测试人员来当经理好了。

我说,怪不得每次去检查身体问化验医师有没有问题正不正常,化验医师总是不耐烦的说去问医生呢。

我问:什么测试才是良好的测试呢?

神说,你觉得呢?

我说,测试的目的是发现缺陷,所以发现的缺陷越多,那么测试越好。

神说,然后呢?