2010年为《程序员》杂志写了一篇《敏捷测试的方法和实践》,我们可以回过头来,看看过去的一年,敏捷测试发生了哪些变化。首先,我做了一个实验,分别打开2010年和2011年的“STAREAST Conference at-a-Glance”,输入Agile,2010年显示10个结果,而2011年显示17个结果,有一个很大的增长,说明敏捷测试越来越引起大家的关注。这只是一个表面的现象,我们还需要真正了解发生了哪些实质性的变化。
举一个例子,《敏捷测试:测试人员和测试团队的实践指南》的作者Lisa Crispin在StarEast 2011上有一个演讲——Agile Testing: After the First Year, What’s Next? 其中提到,我们从传统开发方法转向敏捷方法,由于开发人员掌握了测试驱动开发(TDD,Test Driven Development),而测试人员部分地实现了验收测试和回归测试的自动化,所以我们活下来了,但我们在接下来深入实施敏捷测试时,还会面临新的挑战,甚至要克服更大的困难。当测试人员有了一年的经验,并拥有了敏捷方法的价值观、原则和实践之后,我们还不得不考虑如何不断改进持续的发布、如何有效地管理技术债务、如何对客户的需求有更好的理解,这就要求我们掌握更深的敏捷测试技术,例如将“精益(Lean)方法”用于改进敏捷测试的绩效,以及重构自动化测试的设计或脚本以提高投入产出比。
TDD 向ATDD、BDD转化?
以前人们谈到敏捷方法,就会谈到TDD或UTDD(Unit TDD),但是究竟有多少个公司在采用TDD方法来写代码?而在采用TDD开发方法的公司中,又有多少程序员在全面使用TDD方法呢?TDD是一个纠结的问题。一方面,TDD的确是一个好东西,先写测试用例、后写代码,保证程序员第一次就把代码写对,也彻底解决了代码的可测试性问题,在代码层次上把缺陷的预防做到淋漓尽致。另一方面,多数项目很紧张,不可能给程序员足够时间去实施TDD,程序员对实现有极大兴趣,而对测试缺乏兴趣,多数程序员也不愿意或不会主动去做TDD。这样,TDD实践还存在较大困难,有比较多的争议。我看到一位作者写道:组里头TDD说了3年,据我所知,看完两本TDD名著,并坚持写单元测试的人只有我一个(我组里有开发人员15名)。
图1 TDD和ATDD之间的关系 为了解决TDD实施不力,在过去一年,越来越多的人关注ATDD,即验收测试驱动开发(Acceptance Test Driven Development)。从2003年开始,人们逐渐实践TDD,而ATDD 是在2007年Lasse Koskela写了一本书《测试驱动:Java开发人员的TDD和ATDD》 ,才开始引起大家的更多关注。从那时算起也有四年了,但在国内,则是最近一两年的事。当然,我们可以将TDD和ATDD结合起来使用,形成一种混合的方法模型。TDD和ATDD之间的关系,可以用图1来描述。
接着,BDD(行为驱动开发,Behavior Driven Development)也开始大行其道,那BDD是不是“做得比较好的TDD”呢?概念越来越多,概念的界限就难以确定,BDD可以看成ATDD的延伸,只是BDD更强调用户的视角、用户的行为,为ATDD注入了“Given,When,Then”这样特定的需求描述语言。2009年,BDD创始人在伦敦发表的“敏捷规格、BDD和极限测试交流”中,对BDD给出了如下定义:
BDD是第二代的、由外及内的、基于拉动的(pull)、多方利益相关者的(stakeholder)、多尺度的、高度自动化的敏捷方法。它描述了一个交互循环,可以具有带有良好定义的输出(即工作中交付的结果):已测试过的软件。
但这个定义看起来还不够好,至少让我们明白起来还有一定的困难。实际上,BDD具有自己特定的“Given,When,Then”行为描述语言,和敏捷的user story极为吻合。所以“Given,When,Then” 行为描述语言才是BDD最显著的特征。
TDD在写测试用例时,常常会提出“我们应该先测什么”,然后针对测试的条件来填充代码,而BDD则试图换一种方式去思考问题,即问自己“预期的行为是什么?”,可能会写出结构更好的代码。说到底,BDD更关注客户的需求,通过了解客户的不同行为,对客户的需求有更深刻的理解,从而借助对需求逐渐深入的理解来驱动软件开发。
TDD更重要的价值是其思想,就像传统的制造业,一定是先知道产品的质量标准或验收标准之后,才去设计、制造。从这个思想来看,TDD、ATDD和BDD都是一样的。不一样的是其具体的操作方法或实践,我们可以说,ATDD和BDD有一定的进步,但还没有到达完美的地步,还有提升的空间。在未来,首先就是如何灵活结合BDD、ATDD和TDD来构成一个测试体系,是一个发展方向;其次,就是在BDD、ATDD和TDD最根本的、共同的思想基础上,构成一个全新的、更完善的敏捷测试框架。后者的可能性更大。
探索式测试的地位
在过去一两年,在敏捷方法中探索式测试(Exploring Test,ET)也是一个热门话题,甚至有些人想用探索式测试来代替传统的用例测试(case-based test)或脚本测试(scripted test),走向另一个极端。探索式测试是对用例测试的补充,在非敏捷开发方法中也可以使用。只是在非敏捷开发方法中,有较为严格的需求规范和设计文档,有充分的时间去设计足够的测试用例,探索式测试只是作为一种辅助的手段发现一些隐藏很深的缺陷,并成为一种产品学习的工具以完善测试用例。然而,在敏捷测试中,由于迭代快、需求变化相对频繁,缺乏详细的需求描述文档和足够的设计描述文档,探索式测试发挥更大的作用,甚至在新功能测试中发挥决定性的作用。需要提醒的是,在敏捷测试中,回归测试应该仍然以用例测试为主,可以这样说,回归测试还是百分之百的用例测试。
探索式测试,实际早在1984年就由James Bach和Cem Kaner提出来,但为什么直到最近几年才比较热呢?这主要得益于敏捷开发方法的兴起,而敏捷开发方法的兴起又得益于互联网应用的迅速扩张。大家都知道,互联网应用越来越普遍,竞争越来越激烈,迫切要求互联网应用产品发布要快,再加上许多互联网产品的开发,都极具创新性、摸着石头过河,其需求不明确,要求开发周期短,频繁发布新的版本,及时获得市场和用户的反馈,不断修正以更好地满足用户的需求。针对被测对象,所掌握的信息不够充分的情况下,探索式测试就是一种很有效的测试方法。而且,把测试过程写下来(脚本化)需要时间,在敏捷测试中,时间显得更为珍贵。如果需求变化快,脚本化的测试用例维护成本也过高、甚至是极大的浪费。探索式测试的倡议者还认为,测试执行过程应该是智力活动的过程,这一过程越善于思考、越流畅,我们越有机会发现缺陷。而用例测试方法,有太多的停顿、不够流畅,会破坏这一过程。