从 TDD 到 BDD

转自http://www.cnblogs.com/lidaobing/archive/2010/07/18/1779987.html

最近在学 ruby, 也用了 rspec, 传统的 xUnit 是 TDD 指导思想下的产物, 而 rspec 则算是 BDD (Behavior Driven Development) 影响下的产品。


TDD 和 BDD 区别究竟何在呢?

首先是思路上的区别, 传统的 TDD 关注的是接口是否被正确地实现了, 所以通常每个接口有一个对应的单元测试函数。而  BDD 通常以类为单位, 关注一个类是否实现了文档定义的行为

具体从 rspec 的实现上来看, 主要有如下的不同

1. rspec 可以成为设计的一部分  , 你在设计一个类的时候, 一般会先写这个类需要实现哪些功能, 然后在逐个实现需求, 比如 XmlParser, 你会先计划他有三个特性, 支持从字符串初始化, 支持"=="符号, 支持序列化为字符串, 这时候你就可以写下如下的测试代码

# xml_parser_spec.rb
describe "XmlParser" do
  it "should support init with string"
  it "should support =="
  it "should can convert to string"
end

此时运行如下的命令就可以看到你规划的类行为
$ spec -f n xml_parser_spec.rb
XmlParser
  should support init with string (PENDING: Not Yet Implemented)
  should support == (PENDING: Not Yet Implemented)
  should can convert to string (PENDING: Not Yet Implemented)
...

上面的输出可以清晰地看到 XmlParser 需要支持的功能。你不用把这些功能需求记在脑子里, 也不放在你的 TODO 列表里,直接放这儿就行了


2. 使用一个句子来描述你要测试的行为, 而不是简单的重复被测试的接口名 , 比如一个 典型的测试
it "should return [Miniblog] with different id" do
其中的 "should return [Miniblog] with different id" 就是这个测试的描述

3. 多级的 context, 便于将类的行为分到多个组, 同时每个组可以有不同的上下文环境(setUp+tearDown) , 比如一个 xml parser, 如下所示的测试代码可以把行为分为两组,在遇到合法数据时的行为以及遇到非法数据时的行为

describe XmlParser do
  context "with valid data" do
    before do
      @valid_data = "<a>123</a>"
    end
    ...
  end
  context "with invalid data" do
    before do
      @invalid_data = "<a>123</b>"
    end
    ...
  end   
end

4. 支持自动文档化 , 在1里已经可以看到 spec 支持生成一个简略的文档来描述你的对象, 下面是一个比较长的例子用于描述 Douban::Authorize 的功能, 树状的结构把类的功能分到了多个小组


5. 表述更接近自然语言的习惯 , 比如 xUnit 通常使用 assertEqual(a, 1), 而 rspec 经常使用 a.should == 1

相对于 TDD 来说, 这些都不是什么革命性的突破。但是思路的转变,能够让你的开发更流畅。

首先你在设计时就可以开始写测试代码, 在开发完成后可以通过 rspec 生成的文档来快速浏览你是否完成了所有特性。这些性质都能让测试驱动开发更容易推广。从我的工作经验来看, 由于种种原因 (比如没有迭代周期, 缺乏 code review 制度, 没有硬指标的覆盖率要求...), 大家的测试代码写得很少。而在 rspec 的帮助下, 直接看 rspec 生成的文档就可以督促大家补全测试。

转自http://blog.csdn.net/ant_yan/article/details/7272612

敏捷开发有许多种方法,但不管采用任何一种,测试都是实施敏捷的基础,及时的验证代码的正确性,系统功能的健全与否,及时的反馈,及时的叫停……都是保证敏捷的基础。所以大量的快速的自动化测试,才能保证敏捷开发在快速迭代中仍然不怎么丢失软件的质量。

所以,在敏捷开发里一直都有一种说法叫“代码即文档”,而且测试代码也成了功能代码的使用文档。敏捷里强调的TDD(Test-driven developmenet, 测试驱动开发),就主要体现了这种思想:根据设计编写测试-> 实现设计的功能 -> 用测试代码验证 -> 重构实现代码 -> 改善设计 -> 再次回到根据改善的设计编写测试。反复循环下去,就是TDD所倡导的流程。

TDD的好处:1. 能驱使系统最终的实现代码,都可以被测试代码所覆盖到,也即“每一行代码都可测”。2. 测试代码作为实现代码的正确导向,最终演变为正确系统的行为,能让整个开发过程更加高效。TDD的不足之处或者说还不够完善的地方,是对设计和测试的编写没有一个明确的方针。作为整个循环中的向导部分,如何保证根据设计编写的测试就是最终用户所期望的系统行为?如果这一部分模糊了,那么后续所有环节几乎都要受到影响。所以,再次基础上,敏捷社区又有人提出了BDD的概念,即“行为驱动开发”。

BDD(Behavior-driven development)把TDD中模糊的那一部分给明确了,强调开发、测试、BA、客户等所有项目相关人员都用自然语言来描述系统的行为。大家看到的描述一致,读到的内容一致,于是最终测试驱动开发产出的结果也应该是最符合用户期望的。所以在BDD的倡导下,介绍了一种简洁的类似自然语言叫Gherkin Language。下面看一个用Gherkin Language描述系统行为的例子:

[plain]  view plain copy print ?
  1. As a xxx [Role]  
  2. I want to xxx [Feature]  
  3. So that I can xxx[Benefit]  
  4.   
  5. Scenario 1: create user  
  6. Given a admin log into the system  
  7. when he create a user with name 'mike'  
  8. then mike should be able to log into the system  

随着BDD的出现和发展,使用大家都能轻易理解和认知的语言来描述系统的行为并创建User Story,TDD的反复循环的流程也就能更顺利的进行下去了。BDD的核心价值是体现在正确的对系统行为进行设计,所以它并非一种行之有效的测试方法。它强调的是系统最终的实现与用户期望的行为是一致的、验证代码实现是否符合设计目标。但是它本身并不强调对系统功能、性能以及边界值等的健全性做保证,无法像完整的测试一样发现系统的各种问题。

有种说法是BDD是TDD的进化,其实笔者看来,没有孰优孰劣,它们的本质和目标都是一致的。只是在实施方法上,进行了不同的探讨来完善整个敏捷开发的体系。如果BDD书写的User Story或者叫测试用例,不能作为开发、测试和客户等人共同参与和看到的一致性内容的话,那么它的价值也几乎得不到体现。另外一点,由于BDD不能代替完整的测试,旨在描述系统的行为,所以就像Gherkin Language的例子所体现的那样,关键是“简洁”,切忌啰嗦的想把每一步操作和任何情况都说得很清楚。

最后总结:TDD的迭代反复验证是敏捷开发的保障,但没有明确如何根据设计产生测试,并保障测试用例的质量,而BDD倡导大家都用简洁的自然语言描述系统行为的理念,恰好弥补了测试用例(即系统行为)的准确性。(不管以上理念是否先进,切忌盲从和滥用)
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值