本文根据中生代技术群分享整理而成,具有多年软件研发经历的刘朋为大家分享atdd,tdd,bdd的那些事,为大家分享“以终为始的软件开发”经验。
<b>文章正文</b>
我分享的主题是tdd,但是其实涵盖的领域会更宽泛。于君泽在前几期里面分享了“以终为始的架构设计”,其实我的tdd分享并不会仅仅拘泥于tdd,或者说我更想和大家讨论一下“以终为始的软件开发”,这个题目也许更为恰当。
所以,我其实想讨论的是:作为软件开发研发团队,当我们从客户(或者客户代表product owner)那里获得了对软件产品的需求,到研发团队给客户交付了满足预期的产品,这中间,怎么才是一个有效的,高效的流程和方法。这是我感兴趣的话题,也是我作为研发经理在日常工作中一直在思考和探索的问题。
为了回答这个问题,我们这次先把目光聚焦,我们先来看看三个敏捷社区软件开发人员都会耳熟能详的模式——atdd,tdd和bdd——能怎样贡献到“以终为始的软件开发”这个目标。
所以,这次分享的第一部分,我们就谈谈:
要谈这个话题,我们首先得了解这三个dd是什么。在wiki上,对三者的定义是:
atdd
acceptance test-driven development (atdd) is a development methodology
based on communication between the business customers, the developers,
and the testers.
tdd
test-driven development (tdd) is a software development process that
relies on the repetition of a very short development cycle: first the
developer writes an (initially failing) automated test case that defines
a desired improvement or new function, then produces the minimum
amount of code to pass that test, and finally refactors the new code to
acceptable standards.
bdd
in software engineering, behavior-driven development (bdd) is a
software development process that emerged from test-driven development
(tdd).
其实看了这三个wiki上的定义,我只想说:“然并卵”。说得很玄乎,但是到底什么是atdd,什么是tdd,什么是bdd,它们的关系和联系是怎样的呢?它们如何协同应用贡献到“以终为始的软件开发”呢?
为了解答这个问题,我们给大家整理了一个30秒弄懂atdd的定义:

如果翻译成中文,那就是:
<b>【30秒搞懂atdd】</b>
atdd (验收测试驱动开发)就是一种让整个研发团队(po,dev,tester)一起协同讨论和澄清验收标准(包含实例);并基于此提炼出一系列具体的验收测试(at),然后再开展具体的软件开发和编码的实践。
atdd背后的逻辑:最好的验证一个研发团队是否对客户需求有统一的理解的方法就是对客户如何验收有统一的理解。具体到开发工作中,就是有对dod有共同的理解。
有人说,嗯,懂了一些了,但是还是不完全懂~没有关系,咱们上图:
图1 atdd 4d循环
哎呦,这个图不简单了,一下子就把atdd,tdd和bdd的关系和联系展示出来了。如果我们把这个atdd cycle放在scrum实践中,这个图长这个样:
图2 atdd cycle in scrum
下面,让我们按照atdd 4d的循环,一个d一个d的来解释一下。
atdd循环之discuss
目标
充分的理解客户需求和客户价值
充分利用团队成员的不同知识和技能理解需求的不同方面
让所有团队成员都获得对需求的一致理解
希望解决的问题
对客户价值理解不正确,后期验收不通过
开发和测试人员对需求理解不一致
输入
从用户或者用户代表(po)来的用户需求(用业务领域的语言描述)
输出
端到端的用户故事(end-to-end user story)
采用的实践
六顶思考帽
一点点解释:这第一个d(discuss),目标就是让所有接下来会参与到软件开发中去满足客户需求的各方利益相关者(stakeholder),都能够在一开始就对用户想要什么有统一的理解。因此,这个讨论需要客户(或者客户代表),架构师,开发工程师,测试工程师,系统测试工程师,系统集成人员,等等相关各方都能派代表参加。在初期达成的一致将会大大减少后期的扯皮。这在我们nokia的实践中已经被证明是能够很大程度的减少软件开发中不必要的浪费——代码完成后的需求扯皮。
另一方面,为了达到这个目的,需要有讨论,讨论就要开会。那怎么开这个会,也是非常有讲究。在我们的实践中,我们经过尝试了不同的方法,最终觉得使用“六顶思考帽”的方式是非常有效的方式。(关于什么是”六顶思考帽“,请自行google之,这里不再赘述)。
在具体的实践中,一个需求讨论和澄清的会议的流程这样的:
蓝色帽子——会议主持人
【第一步·白色帽子】收集关于这个需求的<b>背景,事实和数据</b>,供进一步的讨论。注意,这里不讨论任何怎么做
【第二步·红色帽子】在收集完事实之后,所以参会人员的感受如何,是否觉得已经有重复的事实可以进入下一步的需求澄清讨论
【第三步·绿色帽子】讨论正常场景下,客户需要的是什么。举个例子,如果需求是一个用户名/密码登录界面,那么正常情况下软件需要呈现的功能是什么。
【第四步·黑色帽子】讨论异常场景下,客户的需求意味着什么。继续上面的例子,在异情况下,比如双十一超大访问压力下或者遭受黑客攻击时,登陆模块需要呈现的功能是什么。
【第五步·黄色帽子】决定以上绿色帽子和黑色帽子讨论结果的价值和优先级排序。那在上面的用户名/密码登陆模块例子中,如果对于有限的研发资源和交付时间压力,团队是先专注哪些功能,是正常情况,还是异常场景处理。
【第六步·红色帽子】最后,再询问大家的感受如何,今天的会议是否达到了目的,所有stakeholder都对用户需求是什么达成了一致。
好,说道这里,大家可能要问:那我们如何表达对用于需求的理解呢?如何确认所有人都有了一致的理解呢?那就到了atdd循环中第二个d(distill,提炼)。
atdd循环之distill
根据团队对需求的充分讨论,提炼出需求(feature)的验收标准以及相应的测试点
验收标准将成为后续验收测试用例和产品代码开发的出发点
验收标准不清晰,不一致,导致后期无法验收并产出用户价值
避免出现传统测试中的“bug海啸”
端到端的用户故事(end-to-enduser story)
利用bdd方式描述的验收标准(acceptancecriteria)
bdd的“given,when,then”行为描述语言
说道这里,就不得不说一说bdd。bdd的提出者dan,是这么描述bdd的:
"bddis a 2nd generation, outside-in, pull-based, multiple- stakeholder,multiple-scale, high-automation, agile methodology."
<b>“bdd是第二代由外至内的、基于拉动的、多利益相关者的、多尺度的、高度自动化的敏捷方法。”</b>
但是,dan自己也承认,他都不知道这段话说了什么j然而,我们不得不说,bdd的一个关键,看似微小,的改变就是在描述测试点的时候,用“should”替代了“test”。也就是说,<b>你可能会听到在讨论验收标准的时候,问题是“预期的行为是什么?”</b>,而不是“我应该测什么?”举个例子,下面图中女po和身边的两位研发团队骨干关于“首单打折”这个用户需求
的讨论完全不在一个频道上,从业务语言,到伪代码,到实际的测试函数。无论用哪一种作为描述验收标准的方式,都无法使所有stakeholder都能理解,并且达成一致。
因此,如果换成bdd三段论given-when-then模式,将会是下图这样。可以看到,现在所有人都能够用同样的语言,并且是基于软件应该有怎样预期的外部可观察行为的角度,来统一验收标准。而given-when-then也天然可以非常容易的在接下来的步骤中转化为测试用例和指导代码开发。
好,到这里,我们已经有了用bdd的三段论(given-when-then)描述的验收标准,而且所有的stakeholder都有了统一的认识。接下来,我们就可以开始软件设计和编码,以及测试了。那就到了:
这一步就很简单,研发团队可以使用诸如tdd的模式进行代码开发;同时,测试团队根据验收标准开始准备验收测试(可以是自动化,也可以是手动)。
当代码编写和测试完成之后,那就进入了最后一个环节:演示和验收。
<b>atdd循环之demo</b>
根据scrum团队实现同意的definitionof done (dod)对本sprint产出的软件进行验收
团队对验收标准不清楚
团队对验收标准有不同的理解而产生争执
产出的代码虽然工作,但是没有创造客户价值
经过了测试的软件
通过了验收标准的可工作和可以发布给客户的软件
acceptance test case作为验收重要指标
设定对于ut覆盖率,测试自动化率的硬性指标
在这一步中,如果一开始所有的stakeholder都对验收标准达成了一致,那这里的验收就变得非常简单:就是把验收标准拿出来,验证其中每一个given-when-then是否都有相应的测试用例覆盖;如果需要,po还可以挑选若干关键验收标准进行现场演示和验收。
好,说道这里,我们再把atdd cycle拿出来,大家现在是不是可以总整体上理解atdd,tdd和bdd这三者之间的关系和联系。以及它们三者如何有机结合,来完成“以终为始的软件开发”这个目的了呢?
那我们第一次分享就到这里,我们下次来聊一聊:tdd三原则,同时,我们也来尝试着回答这个非常挑战的问题:tdd死了吗?
q: 你们有没有核心人员,或多人流动,导致需要重新和新来人员统一产品定义和验收标准的情况?是如何处理的。
刘朋: 关于人员流动导致需要重新定义产品验收标准的问题,我们之前没有用bdd来描述test point之前,也很麻烦,就是需要有transfer的成本,但是现在我们的grooming输出的都是标准格式,用客户(po)可以看懂的语言描述的验收标准,其实这个成本就小很多了,因为这些test point(验收标准)都是很易懂的
因为如果不“干活”的po都可以懂起,那就不需要transfer成本了噻,哈哈
q:如何提高和改善tdd的开发效率,尤其是在项目开发过程中。我有专门为公司的ui开发框架写过自动化测试,测试开发实际花费的精力和时间是很多的,如何提高这种开发效率呢?
刘朋:回答问题一如何提高和改善tdd的开发效率:其实kent beck说的tdd不是银弹,所以并不是所有场合都需要tdd或者适合tdd,比如ui,就不适合用tdd的方式开发;但是如果你说web ui的test automation,那就是acceptance test的问题,是atdd的问题了,那就有很多工具,比如selinimu等等工具来提升自动化测试的效率
q: 验收测试po要参加吧?还是只参加demo部分?
刘朋: 验收测试,在sprint review上area product owner会作为po的代表(如果po不能参加的话),去验收所有的acceptance test是否都pass
q: 这种以始为终的思想,在推动开发人员思维习惯转变过程中,能否可以分享一些经验和关键点吗?
刘朋: 关于“以终为始”观点的改变,其实atdd是促使大家观念转变的第一件事情,第二件事情是“逼迫”大家(至少初期是这样),用bdd的方式去描述系统应该怎么工作,应该怎么验收,而不是应该怎么测试;第三件事,是让大家体会tdd的好处,因为tdd其实也是在潜移默化的让大家以终为始的思考
其实tdd不是银弹,但是tdd的思想“以终为始”是银弹
因为一开始代码或者设计得可测试性就很低——因为没有“以终为始”
所以多管齐下,让大家看到这么做的好处:和po沟通更顺畅了,开发和测试终于有共同的语言来描述验收标准了;代码终于不用后补ut了,可测性提高了,都会鼓励大家继续用“以终为始”的方式思考
刘朋:嗯,其实kent beck自己也说,即使tdd有一天死了,但是tdd带来的思维的变化-”以终为始“的思考方式,绝对不会过时:)所以这就是为什么要把atdd,tdd,bdd放在一起,放在一个整体的图景中去理解的原因。
江湖:以终为始 我喜欢,做设计 做架构何尝不是如此
刘朋:这就理解了君泽的架构也是“以终为始”,都是相通的~
其实我特别同意并不是所有team都需要tdd,或者所有项目都需要tdd,kent beck自己也说了farewell tdd,但是他也说了tdd may die, but long live testing!
<b>分享者简介:</b>
刘朋,诺基亚程度研发中心软件研发经理,从事软件研发8年,做过软件工程教练,敏捷教练,致力于探索大规模软件中高效能团队进化之路。
中生代技术群微信公众号