最近国外博客上掀起一场关于Automation Acceptance Testing Tool的讨论。如果没听过这个词,这里是简单介绍:它是指一份可执行的需求文档,有很多名词:Acceptance Testing, Story Testing, Bahavior driven development。讲的大体是同样的意思。要让需求文档(或者验收文档)可以执行,当然需要工具,最著名的大概是Fit/FitNesse,还有cucumber,rspec,StoryTeller,Robert Framework,Machine-specifications(MSpec)……
下面是我对这场讨论的介绍,有些是直译,有些是意译,如果有兴趣,最好直接看原文链接。
有人问James Shore关于验收测试的经验,James Shore的回答是:他认为Fit 和其它敏捷验收测试工具cost more than they're worth。理由是:
1,这些工具的本意是让真实的客户来写Example,可现实是,客户对写Example不感兴趣,而对别人写的Example又不理解或不信任。于是,编写Example的任务落到了Tester头上,这样就达不到“客户与程序员加强交流”的原始目的了。
2,另外,这些工具写的测试往往是end-to-end的(端对端,UI驱动),这样的测试往往很慢并且脆弱(UI很容易变),不易维护,又没有相对应的重构工具。总之,它的维护成本是个问题。
综上,他不再推荐使用这些工具,但在面对复杂需求时,他仍然会让客户写Example,只是这些Example不再写成FIT测试,而是用来形成TDD。
作者讲述了Acceptance Testing的价值:它是一个“活文档”。
大意是:常规文档容易过时,代码又不易理解,那么Story Testing(Acceptance Testing)正好集中了两者的优点且避免了两者的缺点:它因为需要被执行,所以不会过时,并且由于使用自然语言,因此容易理解。
文中另有一个链接,也不错,验收测试失败的十大原因。
George Dinwiddie的回应是:以他的经验,没有自动化验收测试的团队,增加Feature的步伐会越来越慢,因为有越来越多的东西需要重复测试。为什么回归测试必不可少呢?有人会认为如果只是很小的代码改动,很多东西都不需要回归测试,但他引用Jerry Weinberg书里的观点认为事实是:“a one-line change is more likely to introduce a defect than a larger one”,因为程序员做小改动时,会放下心里防卫,所以不去确认整个产品是否仍旧正常,这往往导致bug的出现。
对于James说的两个问题:
1,客户不愿意写Example,George认为这不是问题,Example不一定要让客户来写,重点是参与,重点是让客户和程序员/测试人员的交流更加频繁。
2,Acceptance Test的维护问题,George认为这的确是个问题,但应该让我们软件行业去解决它(努力写出更好的自动化测试工具),而不是因此而抛弃它。同时还推荐了一篇文章 ,关于在现有工具的限制下写出维护性更强的自动化测试。
James Shore为自己抛弃Acceptance Testing的想法做了进一步阐述,说,因为他有Cost更低的替代物。这篇文章可以说是一个XP实践的“小全”。
文中说,测试无非是为了减少defect,他把defect分为四种,并针对每一种都给出若干个Practice来应对。
1,Programmer errors:指程序员理解了需求,也有正确的设计,但有可能是算法写错了,或者拼写错误造成的bug。
2,Design errors:设计错误,指当时能够work,但是设计不合理,随着需求的变化,引发出bug,文中称之为bug的“温床”。
3,Requirements errors:对需求理解有误造成的bug。
4,Systemic errors:一切都对,唯独一些东西没考虑到,比如安全漏洞,内存泄露,死锁。
1,TDD:TDD不等于Unit Test,TDD包含三种:Unit Test,Focused Integration Test,end-to-end Integration Test(James强调最后一种由UI驱动的自动化测试不可太多,理由仍旧是UI的易变性引发的测试代码的维护性问题);
2,Pair Programming。
1,Simple Design;
2,Incremental Design and Architecture;
3,Refactoring(他的团队在每个Sprint中都会留一定的Slack Time用来重构,以偿还technical debt
4,发现bug尽快修复(或者做决定不值得修复它),理由是:a)时间越长,修复的代价越高;b)根据二八原则,这个bug很可能是由20%的代码引发的80%的bug中的一个,通过写Unit Test来修复这个bug,可以杜绝以后类似的bug。(这也是需要Unit Test的另一个原因:它在一堆类似的bug上可以做到一定程度上的一劳永逸。)
2,Customer Examples: 作者认为这是遗留的FIT测试留下的最有价值的东西。Domain Rule example可以直接对应到程序的概念里,特别是使用Domain-Driven Design的时候;如果客户的Example太过于High level,也可以在TDD的过程中把它分解成Unit Test或者Focused Integration Test(应该避免end-to-end integration Test)。
3,Customer Review:客户说done,才算done。
4,Bring testers forward:让Test参与需求讨论,协助客户写出Example。强调的还是跨功能团队。
1,Exploratory Testing: 事实上,在理想的Agile团队,探索性测试是几乎唯一一个需要QA手工进行的测试,其它大部分测试都已经自动化了。
2,Fix the Process:结合根源分析法,如果有什么错了,要责怪并修正流程,不要责怪个人。根源分析法一个简单的实施办法就是针对某个问题,问5个why。(比如某个程序员写的代码总是很多bug,返工太多,这时如果不使用根源分析法,直觉就会认为这个程序员技术不行、不负责。这时就违反了“不要责怪个人”的原则。让我们问5个why:为什么他总是引入bug?因为他 技术一般,设计不正确。为什么设计不正确?因为他没有跟别人讨论,自己闷头做自己的。为什么他不跟别人讨论?因为团队没有讨论的气氛。为什么没有讨论的气氛?因为大家手头都有事情需要按时完成,时间很紧迫。为什么会有这个现象?因为我们的Task是领导Assign给个人的,如果不按时完成,会影响个人的Performance。——到此,也许还可以问下去,但显然我们找到了一个与Scrum精神格格不入的问题:我们被push,而不是敏捷建议的pull。)
James Shore说这些都是他的团队在做的XP实践。
Ron Jeffries总结了以上内容,然后说:如果别的团队也像James的团队这样实施XP实施的这么好,他也可以不需要Acceptance Testing,但Automation Story Testing(也就是Automation Acceptance Testing)仍旧是最简单的防治bug出现的方式。并总结说,进行验收测试的团队还处于“守”或者刚达到“破”的阶段,如果团队进入到“离”的阶段,是可以drop掉验收测试的,但是仍然要警惕:
Acceptance Tests are at shu level and the bottom half part of ha level. When your team is at or near the ri level, you’ll have enough other rigor in place to safely drop them. Even then, keep a weather eye peeled for increases in defects. We’re not as good as we think we are.
(我觉得他整篇文章的言下之意大概是:如果你的团队足够优秀,当然会有Alternative,不要Acceptance Testing是可行的。但问题是,你的团队有像James的团队一样优秀吗?)
Lisa Crispin 分享了她的几个观点:
1,首先应该问:采用任何优秀实践,是因为它们可以解决我们的痛苦,提高我们的产品质量?还是只是因为跟风?并举例说:很多人看到差劲的软件开发流程(没有采用好的实践),就说它是Waterfall流程,事实上,采用Waterfall流程的团队仍旧可以采用很多好的XP实践,反过来,如果团队成员没有一颗积极向上的心,即使采用Agile,仍旧注定失败。(If people have the wrong motivations or are lazy and undisciplined, I don’t care what process you follow, it’s going to keep failing.)所以她说,团队或公司要有一种Learning Culture。
2,关于Team Values:向Agile改变需要从团队的深刻反省开始,比如XP里的“Whole Team”,Dev和QA都是属于Development的角色,他们对质量和测试拥有同样的职责。其次,团队成员应该有一致的价值观,如果成员开始找理由:“因为架构的关系,我们没法做TDD;因为产品太复杂,所以我们没法做CI(持续集成)”,那么说明我们没有真正的对质量负责,正确的态度应该是:做TDD有障碍,做CI有障碍,但让我们一起找办法解决它!
3,Value-guided Experimentation。当团队变得自组织,当团队对于Team Value有了一致的理解,那么当他们碰上任何问题,都会根据团队的价值观来做出决定:采用什么好的实践?使用什么工具?当团队开始作为一个整体来做决定时,前途开始光明。
4,One Right Way(这段比较经典又篇幅短小,就不翻译了)
I can’t tell you the one right way to test and develop software. If you don’t have the enlightened management I’ve described above, try to enlighten them. Ask them to identify the biggest pain points and work with you to experiment with ways to address those. If you don’t have the motivated teammates eager to take responsibility for quality and testing, try leading by example. Show what you do with your own passion for doing good work.
The one right way for your team to code and test will continually evolve over the years. In fact, I’m sorry to tell you that you’ll never find the one right way; it’s a moving target, but you’ll get closer and closer to it.
Please read all these blog posts and as many books as you can. Participate in as many online and local user groups as possible. Keep an open mind. Bring the ideas and techniques you learn about back to your team. If one seems likely to help your team overcome a particular obstacle, give it a try. If it doesn’t work, you learned something. If it does, celebrate and move on to the next obstacle.