2010年第9期的《程序员》杂志刊登了荣浩先生的文章《关于测试的八个问答》(在线版本发布在JavaEye上)。这是一篇充满思辨的优质文章,有许多观点值得借鉴。但是,我对如下文字有不同意见。
我说,那么,测试保证了质量?
神说,你觉得三鹿没有测试吗?
我说,....
神说,测试只是提供信息。至于这些信息的定义、重要性以及所要采取的反应都取决于人,而人做出的决定都是感性的,利益驱动的。
我叹口气,说,测试能够保证软件质量。
神说,如果开发的产品本身质量低劣,进行测试你不觉得是浪费大家的时间吗?一段时间发现的缺陷越多,并不意味着剩下的缺陷越少,而是意味着会出现更多的缺陷。
我说,我明白了,测试只是反馈信息,除此之外,并不能做其他任何事情。正如我们去体检,体检报告只能反映当时我们的身体状态,至于健不健康,则取决于我们平时的生活习惯,这是两个分开的事情,体检并不保证我的健康。
神说,是的。
荣浩先生认为“测试只是反馈信息,除此之外,并不能做其他任何事情”。但是得出这一结论的推理过程是不严密的。
荣浩先生先用三鹿的例子精彩地指出一个事实:有些企业的负责人不顾质检信息,出于私利,发布有重大缺陷的产品。在这样的企业里,测试活动不能影响产品生产和发布,不能保证质量。之后,荣浩先生提出,如果产品质量非常低劣,测试可以发现大量的缺陷,但是“边测边改”的混乱过程无助于提高质量。
以上两个观点都是令人信服的。但是,它们是对两个极端情况的分析,并不能得出普遍结论“测试只是反馈信息”。在大多数企业中,企业负责人不会草菅人命,他们被客服电话所折磨,也希望自己的产品能有个好质量。在大多数项目中,代码质量即便达不到卓越,但也能够满足基本要求。在这样的环境中,测试可以保证质量吗?
我的观点是:测试不能“保证”质量,但是测试有助于提高质量。
测试不能保证质量,是很容易理解的。按照现代质量理论,质量不是某个角色的职责,而是整个组织的职责;质量不取决于某项活动,它由所有活动共同构建。在软件生命周期中,战略规划、需求协作、架构设计、编码实现、测试检验、重构优化、推广营销,都对用户可体验的“质量”有重要影响。组织领导、项目经理、程序员、测试员都要对质量负责,他们的活动将共同决定产品质量。
虽然任何单一活动都不能保证质量,但是测试对于提高软件质量有着重要作用。而且,其作用已经远远超越单纯的“反馈软件缺陷信息”。
对于开发人员,测试已经成为一项重要的设计与编程工具。
对于敏捷团队,测试已经成为一项团队支持工具。
对于测试者,测试负责且必须承担反馈信息的职责,但是他可以做得更多。
任何严肃对待软件的开发者都应该谨慎考虑Martin Fowler的话:
The reason JUnit is important, and deserves the Churchillian knock-off, is that the presence of this tiny tool has been essential to a fundamental shift for many programmers. A shift were testing has moved to a front and central part of programming.
JUnit 之所以重要且受到丘吉尔式的赞誉,是因为这个小工具对于许多程序员的根本性转变至关重要。这个转变是测试移动到编程的前沿和中心位置。(摘录自《xUnit Test Patterns · 前言》)
以JUnit为代表的xUnit家族得以流行的根本原因是测试驱动开发(Test Driven Development)被普遍地认同和实施。Kent Beck将一种简单的实践发展为强大的编程工具,单元测试不仅是错误检查者,还是类型设计工具、可执行的规格说明和重构安全网。Jimmy Nilsson将测试驱动开发提升到架构级别,利用具体的测试用例来实施领域驱动设计(Domain Driven Development)。测试不但是单元(类或函数)设计的驱动力,也是体系结构设计的驱动力。
任何设计都要落实到代码且通过测试检验,才算完成。从抽象思考到代码实现的过程是“编写测试,编写代码,通过测试、代码重构”的反复循环。在每一个小循环中,测试、编码、重构都对代码质量作出密不可分的贡献。单独强调某一项活动的贡献或忽略某一项活动的贡献,都是不恰当的。