软件测试宣言的诠释
而此后和业界的测试人员、开发人员交流更多,思考得更多,在测试上的思想更清晰,于是在2012年9月5日在新浪微博(http://weibo.com/1652927771/yArIqoCKW )上发表了自己的个人软件测试宣言:
宣言发布后,得到不少网友的肯定。最给力的,要属@培根芝士牛蛙堡:感觉总结的太到位,can’t agree more了,最近在看《软测之魂》,很多观点都是异曲同工啊,虽说就简单四句话,但是每一句话展开去都能写一本书。还有@让测试飞起来:又见右下八卦图亮点。每当遇到左、右难以分辩时就想到它,并以此为基点,偿试思考再进一步,思丝多而力争不乱。分割线不是直的哟,似乎体现开发中有测试(调试),测试中有开发,而又不完全符合对立统一。
当然,也有不同声音,例如:@胡争辉:首先应当强调产品工程,然后在产品工程中强调需求工程,其次在需求工程的基础上强调品质保证工程。脱离的产品工程的品质保证工程是无本之木,无源之水。这实际和我宣言没有关系,这里丝毫没有否定产品工程,也没有否定需求工程,实际第一句“更鼓励事先确定验证的标准并以此来驱动开发”就是强调需求的重要性。需求是软件开发的源泉,而这里关注点是“软件测试”,比较局限于测试自身的内涵和测试与开发的关系。如果拓展出去,我需要发表我的“软件工程宣言”了。
还有其它有意义的补充:
@程序员邹欣:值得开发,测试,项目管理人员思考。 认可内部测试的重要性, 但更重视产品对用户的长期影响; @王立杰-WangLijie:认可测试对质量的改善,但更提倡质量是內建的; 与@Testin-Daiyibin 讨论之后,增加一条,即:认可自动化测试的价值,但更提倡测试分析和设计的创造性和系统性。那下面回归主题,就我自己的软件测试宣言,逐条分别进行说明,并简要阐述如何将它们应用于实际的软件开发工作之中。
1. 认可测试的价值,但更鼓励事先确定验证的标准并以此来驱动开发
首先认识测试的价值,测试是质量保证的重要手段之一,正如在我的博客中所讨论的“软件测试究竟发挥什么作用?”:
对产品质量完成全面的评估,为软件产品发布(如验收测试)、软件系统部署(如性能规划测试)、软件产品鉴定(第三方独立测试)委托方和被委托方纠纷仲裁(第三方独立测试)和其它决策提供信息;通过持续的测试(包括需求评审、设计评审、代码评审等)可以对产品质量提供持续的、快速的反馈,从而在整个开发过程中不断地、及时地改进产品的质量,并减少各种返工,降低软件开发的成本;通过测试发现所要交付产品的缺陷,特别是尽可能地发现各种严重的缺陷,降低或消除产品质量风险,提高客户的满意度,扩大市场份额,提高客户的忠诚度。通过对缺陷进行分析,找出缺陷发生的根本原因(软件过程中的问题,包括错误的行为方式)或总结出软件产品的缺陷模式,避免将来犯同样的错误或产生类似的产品问题,达到缺陷预防的目的所以软件测试的价值不容忽视,但是我们一直提倡“质量更是內建的(Quality is built in)”,软件产品的质量是在需求分析、功能设计、系统设计、编程等过程中逐渐形成的,事先清楚客户的需求,明确软件产品的验收标准,基于这些需求和验收标准来开发,开发人员清楚自己要实现的目标、清楚待实现系统的要求和限制,在工作中能够第一次将事情做对,或者说,第一次将事情做对的可能性会显著提高,在需求、设计、代码中引入的缺陷就会大大减少。理解这一点并不难,如果还是不能很好理解,就看看砖墙是如何砌成的?是先拉上水准线再墙砌,还是墙砌好之后再拉线来检测?
而且,对测试人员说,全生命周期的测试依据也明确了,能够及时提供明确的质量反馈,测试与开发之间也不容易引起的争议,测试效率也会明显改善。本句宣言和验收测试驱动开发(Acceptance Test Driven Development, ATDD)拥有共同的思想和内涵,无论是在传统研发流程中还是在敏捷过程中,都可以尝试这样去做。虽然在某些项目上需求不够清楚、或需求变化比较大,但也不能成为“自己懒于彻底分析需求”的借口,能明确60%的需求,也不能做到30%就停下来了。 否则,无论是“迭代”、还是“重构”,都是“返工”美化之后的代名词。难道企业希望自己团队常犯错误而不断修正吗?
2. 认可专业测试人员的不可替代的价值,但更鼓励开发人员做好测试
上一句已经回答了测试的价值,而这里是讨论测试工作由谁来做?测试有价值,但不一定由专职的测试人员来做,正如一些公司(如facebook)没有专职的测试人员,软件产品的研发也能正常开展。也许在某些初创的企业、特殊商业模式的软件服务、某些移动终端的且免费的产品等可以不要专职的测试人员,但对大多数软件产品、软件企业还是需要专业的测试人员,因为系统复杂、业务更复杂的原因,更可能是测试本身更需要方法和技术。当我们不能简单地掌握软件产品(系统)的测试方法和技术,就需要专业的测试人员。即使在相对低端的制造业,掌握其工作技能不是很难,但熟练工人的工作效率也是初级操作工的几倍。而软件测试所涉及的方法、技术与工具,从功能测试到性能测试、安全性测试、兼容测试、可达性测试到可靠性测试等,从测试计划、测试分析与设计到测试结果分析,从等价类划分、判定表、因果图到基于模型的测试、自动化测试等,已形成一个庞大的体系,没有专注,很难做得精,不能精通测试,又如何有良好的测试效率呢?没有专业的测试技能,测试的风险也很大。这些内容,在我的另一篇博客“专业测试团队会消亡还是新生”进行了充分讨论。正如网友在本博客上还评论说:“如果没有专业的测试团队,那么天上的飞机一定会无缘无故地掉下来,ICU里面的心电监护仪罢工也不会是新闻,核弹未接收到真正的发射命令而自行启动也不是没有可能,这个世界将不再是安全的世界。”
为什么更鼓励开发人员做好测试呢?这是因为:
单元测试是基础,没有单元的质量,如何有系统的质量?而单元测试主要是在代码层次上展开,而且和编程交织在一起,编程和单元测试难以分开处理,所以单元测试最好由开发人员来做,确保良好的工作效率与工作质量;如果开发了一个测试工具,先让开发人员用起来好,还是只让测试人员用?无论是功能测试工具还是性能测试、安全性测试工具,都可以让开发人员先用,测试的效率会更高。一边构建、一边验证,更能及时发现问题,能更快调试和修正问题,将问题消除在萌芽之中。这也就是为什么我们一直提倡持续构建、持续测试;如果开发人员做更多测试,就更能认识到自己的问题,了解问题产生的原因,将来在设计、编程中更好地避免同样问题的发生,预防缺陷效果更好。这里鼓励开发人员做的测试,主要集中在单元测试(功能、性能方面的测试)、集成测试等方面。而系统的测试、用户需求的进一步验证和确认、大规模的性能测试、兼容性测试、安全性测试等则有专业的测试人员完成。
3. 认可测试计划的价值,但更强调计划是一个基于风险不断调整的过程
这点比较容易理解,做一件事,如果没有计划就比较盲目,失败的可能性就很大。测试计划目的就是明确测试的目标、测试的需求(包括测试范围、测试任务优先级等)、测试风险、测试资源和进度安排等,但同时需求会发生变更、开发的设计与代码质量超出我们的预料、测试工作量估算不足以及其它新的测试风险等各种因素的影响,我们可能需要不断调整测试计划,以适应新的测试需求等。计划重要,但不是一成不变的,也就是我们强调:
测试计划不能停留在文档上面,它是对测试过程的规划与指导,使测试工作开展得更顺利、更有效;测试计划不是一个文档,而是一个计划的过程,适时调整以及时满足项目新的需求;对测试计划的调整也是学习的过程,有利于将来(为下一个项目)制定出更可靠的测试计划。
4. 认可探索式测试的价值,但更希望测试是具有系统方法的、相对规范的过程
我们都知道,测试不能穷尽,测试不能做到百分之百,总是有不能测到的地方,总是有缺陷遗留下来,这就给我们留下了足够的探索空间。探索式测试(Exploratory Testing,ET)的出现正是因为在软件系统中存在许多未知的东西难以得到快速、简单的验证,需要我们转变思路,不要以固定的模式来完成测试,而是要换一种新的模式来进行测试,以提高测试效率。因为需求不清楚、时间紧等各种原因,探索式测试才更有效,在一定程度上是因为软件开发本身的问题,所以,我也戏称“敏捷开发”为“探索式开发”。从这个意义上讲,探索式测试方法是不得已而为之的一种方式。在传统行业,没有看到一种“探索式检验”(除了食品安全检验,在我国还不够成熟,可能会采用探索式检验,哈哈),而是有明确的技术规格,有相应的检测仪器或方法进行检验,可以明确地给出检查结果。
探索式测试作为明确的术语或概念,最早是由测试专家CemKaner博士在1983年提出的,距今天差不多有30年,但绝大多数测试人只是最近几年才听到或熟知这个概念。说明其价值是有限的,如果价值很高,也不至于我们现在才比较关注的。但最近几年探索式测试很热,为什么?
一方面要感谢James A. Whittaker撰写的《ExploratorySoftware Testing》一书,比较全面地介绍了探索式软件测试(国内是2010年引进本书的,但也有不足,我在为史亮和高翔写的《探索式测试实践之路》的序中谈到这一点),对推广探索式测试有很大的促进作用。另方面,在互联网时代,需求衍变越来越快;软件已经成为一种服务(SaaS),迭代周期越来越频繁。敏捷方法开始流行,被软件企业广泛采用,敏捷测试随之而生,正是探索式测试用武之时。而且探索式测试的确给人一些新鲜的感觉,将测试工作变成更有趣的探索式活动,在享受工作的同时完成测试,容易受到测试工程师的欢迎。
探索式测试也在不断发展,人们试图帮助它建立一套方法体系,例如James Bach提出的基于会话的测试管理(Session Based Test Management,简称 SBTM)。该管理方法将测试任务分解成一系列会话(Sessions,发生在特定时间盒内的会话活动,对软件系统的测试就是看成不断地问系统的过程,从系统那里获得答案,探索式测试的会话特征更为明显),测试人员在会话过程中完成一个特定测试任务的设计、执行和记录。
但从探索式测试的“探索”概念本身来看,还是强调“设计与执行”同时发生的特点来看,探索式测试更多强调人的创造性,强调随软件功能的使用对其理解不断深入来发现问题,更强调这种上下文驱动的思维模式,而对验收的标准、验证的具体指标缺乏关注,更谈不上测试需求的分析、测试的系统设计,在系统性和规范性方面有很大的欠缺,所以难以得到国际标准的支持,在多数软件产品的测试工作中探索式测试只能起着辅助、补充的作用。
任何严重的缺陷的遗漏可能给公司带来不可估量的损失,软件测试更注重对软件质量的全面评估,最大程度地减少软件产品的质量风险,从这个意义看,测试目标、测试需求、测试风险等都是非常重要的,需要认真分析,然后在此基础上进行系统的测试设计。测试的结果需要严格的覆盖率衡量,而要确保高覆盖率,需要事先进行精心的设计,从业务流程、数据流程、用户场景等各个方面进行细致分析,采用合适的测试方法设计出相应的测试用例来覆盖流程路径、数据输入空间以及各种产品使用的场景。事先能从需求覆盖出发来设计测试用例,事后还可以从代码覆盖来检验测试的效果。当然,更理想的方式是用基于模型的测试或形式化方法来验证系统的需求,给出更客观的、更准确的质量评估,我们对产品的发布就更有信心,客户就能得到高质量的产品或服务。
5. 认可发现缺陷的价值,但更重视对软件产品质量的全面评估与持续反馈
发现一个缺陷并得到修正,产品的质量就减少一份风险;在当前产品中发现的缺陷越多,就能更多地消除产品的质量风险,这是软件测试价值之一个方面的体现。但我们不能有这样的思想:测试人员发现的缺陷越多,测试人员的价值越大。例如,我们不能一直等开发人员把设计、代码都工作全部完成之后,我们再来发现问题,以体现测试的价值。我们更不能明明看着开发人员犯错误、或者明明知道开发人员可能会在某些地方犯错误,我们也不给予提醒、不给予帮助,而是等到他们做完工作,我们再把问题发现出来,以体现我们的价值。
正确的做法则是及时提供有关质量的反馈,可能是一种质量风险的提示,也可能是一种质量担心的倾诉,更可能是一种有关质量改进的、积极的建议。例如:
在需求分析时,发现需求不够清晰,发现可能给开发、测试带来困惑的地方,都要及时指出来,并帮助纠正。如果发现文档中新增加的功能没有多大意义,或者是自己难以看清楚其功能对客户的价值,就要主动和产品经理沟通,建议拿掉这个功能,或让产品经理解释清楚、说服自己。如果觉得开发任务安排不合理,或觉得开发之前的讨论、培训不够,对业务理解还很肤浅,就要及时和开发沟通,帮忙消除这种潜在的质量风险;如果发现开发不重视单元测试、或者单元测试做得很少,就要协助开发做好单元测试,提供单元测试指导,提供单元测试框架,提供一切可以帮助开发改善单元测试的服务。如果发现个别的开发工程师不遵守编程规范,就要启动质量反馈机制… … …这意味着:
测试工作不是软件开发生命周期的某个环境、某个阶段性的工作,而是贯穿整个软件软件开发生命周期,测试人员无时无刻不在关注质量;测试人员不仅仅要关注已经存在的产品缺陷的问题,还要关注可能导致缺陷发生的问题,尽量帮助产品需求人员、设计人员、编程人员预防质量问题的发生。测试不仅仅是测试人员的工作,而且和软件开发的其他团队(人员)有关系;测试工作不是测试团队内部的事,而是整个开发团队的事。