Skip to content

第24讲:BDD及其自动化实践

在第 20 讲,我介绍了 TDD、UTDD 和 ATDD,主要讨论了需求的可测试性,通过测试先行的敏捷开发理念,比如先建立用户故事的验收标准,来提升需求的质量。今天在 ATDD 基础上,再往前进一步,介绍 BDD------行为驱动开发。

什么是 BDD呢?

BDD(Behavior Driven Development)是由 Dan North 提出来的,他先是在 2003 年开发了一个叫 JBehave 的工具:一个更加关注代码行为的测试工具,强调用自然语言编写测试脚本,可以代替 JUnit。后来经过几年的实践,在 2006 年,Dan North 与 Chris Matts 合作提出了 BDD,把软件行为转化为 Given-When-Then(GWT)格式进行描述,将 BDD 的范围从测试扩展到业务分析,BDD 至此正式诞生。


但是直到 2009 年,Dan 才给出了关于 BDD 的定义,不过仍然让人难以理解究竟什么是 BDD。后来他又给出了一个新的定义,就是下面这个:

BDD 是一个过程,旨在通过改善工程师和业务人员之间的沟通来促进开发项目的交付。BDD 确保所有的开发项目始终关注要交付产品的实际业务需要,即满足用户的所有需求。 ------ Konstantin Kudryashov, Alistair Stead, Dan North


因此,BDD 首要目的是促进团队沟通业务需求,关注真正对用户有价值的需求。BDD 强调团队成员(业务分析、开发、测试)之间通过协作定义软件的行为,即用户与软件进行交互的方式。

BDD 关注业务领域,提倡采用简单且结构化的通用领域语言描述需求,不懂代码的业务人员也可以看懂并且参与编写,以此避免不同领域背景的团队成员之间在理解上的偏差。


正是基于以上两点,BDD 从业务角度可以帮助研发团队快速交付有价值的产品。在采用 BDD 的敏捷开发中,用户故事采用 GWT 格式的自然语言来描述一个用户故事可能遇到的应用场景,并以此做为用户故事的验收标准,如下所示。

  • Given:给定什么上下文/条件 AND/OR 其他条件。

  • When:当什么事件 AND/OR 其他事件 被触发。

  • Then:产生什么结果 AND/OR 其他结果。


示例如下:


As a driver, 
I want the vehicle to determine the speed limit and set the speed to that limit
So that I do not have to pay attention to speed limits

Acceptance Criteria:
Scenario 1:
Given a speed limit
When the car drives
Then it is close to the speed limit but not above it

Scenario 2:
Given the car is moving
When the speed limit changes
Then the speed changes without excessive forc

BDD 和测试的关系

虽然 Dan North 在提出 BDD 概念的时候认为 BDD 是升级版的测试驱动开发,但同时他也在命名的时候用"Behavior(行为)"代替了测试驱动开发中的"Test(测试)"。后来,他一直提醒大家不要以为 BDD 就等同于测试、或者自动化测试,因为 BDD 更关注系统行为和业务需求的沟通。那么,究竟如何理解 BDD 和测试的关系呢?


BDD 强调通过协作和沟通保证业务需求的正确性,但业务需求是软件测试最重要的上下文之一,在前面几讲中,我已经多次强调过这一点。所以 BDD 和测试关系紧密,BDD 为软件测试提供了更为准确可靠的测试需求。


BDD 使用业务领域的自然语言来描述用户故事的具体场景,让验收标准更加明确,保证了用户故事的可测试性。因此,BDD 可以看作是 ATDD 的实例化,即 BDD 是通过上述 GWT 格式所描述的具体场景来建立 ATDD 中的验收标准。BDD 和 ATDD 都是在业务层次上实践 TDD:先编写验收测试用例,然后驱动产品的设计与代码,以此保证软件功能特性被正确的实现,如图 1 所示。


图1 BDD 与 UTDD 的关系


实践 BDD 不一定必须实现完全的测试自动化,但规范化的验收标准为测试自动化提供了良好的基础。或者说,为了更容易、更准确地实现自动化测试,BDD 要求用 GWT 这样的规范格式来描述用户场景。目前有多种能够很好支持 BDD 的自动化测试工具和框架,可以编写并执行自然语言风格的测试用例,并且支持和多种测试执行工具的集成。图 2 展示了 BDD 实践下的用户故事验收测试过程,即:

  • 业务负责人(产品经理)和敏捷团队沟通业务目标及功能特性;

  • 业务分析人员、开发人员、测试人员协作编写用户故事;

  • 建立用户场景,以指导研发人员编写产品代码及自动化测试代码;

  • 测试人员手工执行不能自动化的部分;

  • 提交用户故事验收测试报告,即提供质量反馈。


图2 BDD 与用户故事验收测试

现有的 BDD 自动化测试框架

下面就来介绍一下现有的 BDD 自动化测试框架。


第 19 讲从验收测试框架的角度介绍了支持 BDD 的 Ginkgo 自动化测试框架。这一讲将重点介绍倍受推崇的 Cucumber,然后再看看其他几个常用的 BDD 测试框架,即 Robot Framework、Behave 和 Gauge。BDD 测试框架的共同特点是可以编写并执行自然语言编写的测试用例,从产品的用户价值和业务需求出发,从而实现 BDD。


Cucumber 是基于 Ruby 的自动化测试框架。Cucumber 可以和 Ruby on Rails、Selenium、PicoContainer、Spring Framework 等集成,而且既可以支持 Web UI 的自动化测试,也可以支持 API 的自动化测试。Cucumber 实现自动化测试包括两部分:

  • 一个是 .feature 文本文件,用 Gherkin 语言描述用户场景,并且采用 GWT 格式编写,支持包括中文在内的多种语言。一个 Feature 用来描述一个特性、功能点或用户故事。Scenario 是其中定义的用户场景,说明业务规则的具体示例;.feature 文件相当于可执行的测试用例,也被称为可执行的规范 (Executable Specification),在执行过程中它通过 Given/When/Then 等关键字驱动测试代码。

  • 一个是 Step Definition 文件,针对软件行为的描述编写测试代码,测试脚本支持 Ruby/JRuby、Java、Groovy、JavaScript、C++ 等多种语言。

以在线教育平台查看课程分享收益详情的用户故事为例,一个简单的 .feature 文件示例如下:



Cucumber 自动把测试用例转译成 Step 代码,这样就可以方便添加相应的测试代码了,如下图所示:



为了方便理解,我用中文编写用户场景,在实践中,你完全可以替换成英文。除了 Given-When-Then,Cucumber 常用关键字还包括 Feature、Background、Scenario、Scenario Outline、And、OR、But 等。如果在一个 .feature 文件中的所有场景重复相同的 Given 步骤,那么就可以归并为 Background(背景)。以课程分享功能里面的生成推广海报这个用户故事为例,我列出了其中所有的用户场景。



如果几个场景只是取值不同,即业务的输入或输出数据是变化的,这时就可以使用 Scenario Outline(场景大纲),通过 Examples 表合并需要执行的数据,这也是完成了需求实例化,如下图所示:



这个 Scenario 会执行 2 次,对应 Examples 表中的每一行数据运行一次。关于需求实例化,下一讲将会详细讲解。


Cucumber 还能同时做服务器和手机端的功能测试。Calabash 是一个服务于移动端 App 的验收测试框架,其中核心是 Cucumber,通过 Cucumber 将 Android 的测试框架 Robotium,以及 iOS 的测试框架 Frank 封装起来,使得 Cucumber 的 Step 可以调用 Robotium 或 Frank 进行测试。


图 3 是 Calabash 的工作原理图,其中 Features 相当于前面所说的 Cucumber 的 feature 文件,Calabash Ruby API 是由 Ruby Client Library 支持并与 Instrumentation test server 或 Calabash HTTP server 连接,即实现 PC 端与模拟器或手机真机进行通信,驱动被测应用执行 UI 自动化操作。


图3 Calabash 工作原理图


Cucumber 做到了业务规范和具体的测试代码分离,并且非研发人员也可以编写业务规范。不仅如此,GWT 风格描述的用户场景让软件系统的行为更清晰,因此 Cucumber 不仅是一个自动化测试框架,更是一个团队进行需求沟通和协作的工具。但是单纯从自动化测试的角度来看,很多人觉得固定语法常常让人感觉写起来费时费力。


虽然感觉 Cucumber 就是 BDD 的化身,但它也不一定是最好的或是最适合你的,可以看看其他 BDD 自动化测试框架是不是更适合自己。下面就将几个 BDD 自动化测试框架各自特点做一个比较,如表 1 所示,从而帮助你做出更明智的决定。


表1 常用的 BDD 测试框架的区别和特点

BDD 实践中的常见问题

BDD 做为敏捷方法的一项重要实践,已在很多公司得到推广,其中最重要的 BDD 测试框架 Cucumber 自 2008 年问世以来,累计下载量已经超过 4 千万次。但是,也有很多公司在实践 BDD 的过程中发现效果并没有期望的那么好。


例如,有的公司仅仅是把 BDD 当作提高自动化测试覆盖率的方法,搭建 BDD 的测试框架,按照 BDD 的格式要求编写用户故事、编写实例化的可执行规范、编写测试代码,然后执行自动化测试,却发现自动化测试并不能帮助发现更多的缺陷、提高开发的效率,反而需要花大量的时间去维护这些测试用例。


这就是敏捷实践中所谓的形似而神不似。自动化测试并不是实施 BDD 的唯一目的,更重要的是保证软件按照真正的业务需求来开发并验收。如果在编写业务需求规范的过程中只是走形式,或者根本没有业务人员参与讨论,制定出来的需求规范很难保证正确的定义了系统行为,当然不能有效的指导自动化测试开发,也不能消除因为需求错误或理解不一致而导致的效率低下。


总之,软件产品的开发从理解产品价值、业务目标开始,到定义容易理解的、正确的用户故事的验收标准,测试驱动开发和行为驱动开发都是为了保证研发人员按照用户的需求实现产品的功能特性,并保证团队内外相关人员对需求理解的一致性,从而高效、快速地交付真正有价值的产品给用户。


今天的内容就讲到这里了,我总结出4个要点:

  • BDD 做为一个重要的敏捷方法,首要目的是促进团队沟通和理解业务需求;

  • 通过规范化的用户故事场景描述,BDD 提供了用户故事的可测试性,并且为实现自动化的验收测试提供了很好的支持;

  • Cucumber 做为流行的验收测试自动化框架通过 Feature 文件实现可执行的业务规范,并且支持与多种测试工具的集成实现自动化测试,其他常用的 BDD 自动化测试框架还包括 Robot Framework、Behave、Ginkgo、Gauge 等;

  • 团队在实践 BDD 时应该注意的问题,那就是不要把实施测试自动化做为实践 BDD 的唯一目的。


最后留一个思考题给你:如果在你所在的团队里实践 BDD 会面临哪些挑战?有哪些解决办法?