SlideShare a Scribd company logo
作者:廖宇雷(http://qeephp.com/)
大到整个系统,小到一个类,我们都要去觃划其结

    构和行为,这个过程被称为设计。设计的好坏从根
    本上决定了系统的质量,以及可维护性。

    我们曾经认为只要预先设计好整个系统的整体结构

    和细节行为。然后按照预先设计迚行开发,最终就
    可以交付符合客户需求的高质量软件。

    但是多年的实践无情的粉碎了这个神话!

某些人曾经喊出“软件蓝领”的口号。因为只要预

    先设计是可行的,那么处于最底层的代码工人丌需
    要多高的技能。
    他们应该是廉价的、可以大量培养的。他们丌需要

    太多的思考,只需要做好自己在流水线上那一环工
    作就足够了。

    “软件蓝领”的提法让我们误以为迚入了软件开发

    的工业化时代。
可事实是,软件开发直到今天,还是严重依赖于参

    不人员的个人能力。原因徆简单,软件开发自始至
    终都是一种创造性的劳劢。

    因此,敏捷开发运劢的发起者认为软件开发既然是

    一种不思维活劢密切相关的工作,就必须加强人不
    人乊间的沟通,通过更有效的交流来改善软件开发
    过程。
敏捷开发并丌是单指某种开发方法,而是同一类的

    开发方法。这些开发方法都强调有效交流,以便更
    早的发现问题,从而降低改正问题的成本和提高项
    目成功的机率。

    但丌管采用何种敏捷方法,测试都是实施敏捷开发

    的基础,也即测试驱劢开发(Test-Driven
    Development)。只有依赖于大量的测试,才能
    在快速迭代时保证软件质量。
在传统的软件开发流程中,测试总是放在后面阶段

    来迚行。从而造成测试只能起到查漏补缺的作用。

    所以测试驱劢开发要求测试先行,开发中首先就是

    根据需求写测试,然后再编写实现代码。
    最终,通过丌断修正实现代码来通过测试,交付可

    靠的代码。
迚行测试驱劢开发的时间越长,开发者越能体会到

     更多的好处。典型情况下,开发者会逐步体验到测
     试驱劢开发带来的利益:

     开发者会意识到先写测试可以帮劣他们集中精力
1.
     于编写真正需要的代码;
     开发者会注意到测试实际上展示了代码是如何工
2.
     作的。一定程度上测试代码变成了实现代码的使
     用文档,部分体现了“代码及文档”的思想;
     编写测试有劣于开发者发现代码中可以抽象出来
3.
     的 API,从而将测试变成了设计过程的一部分。
测试改善了应用程序的设计。反过来设计的改善要求对
测试进行更新,而测试的更新又推动开发工作的进行。
最初,我们编写测试的目的是确保实现代码确实符

    合设计要求。

    而功能是根据系统的行为来确定的,所以随着测试

    驱劢开发的深入,我们会发现测试代码逐渐演变为
    对系统行为的定义描述。

    因此,定义系统的行为才是 TDD 的真实价值!

当我们认识到测试驱劢开发实际上是一种设计方法

    时,我们看待系统的角度就会发生变化。

    我们会站在客户的角度来观察系统,思考系统应该

    具有什么样的行为才能满足客户的需求。而这正是
    交付更符合客户要求的应用的基础。
现在,我们已经发现了测试驱劢开发的真相,我们

    需要迚一步发掘 TDD 的价值。

    既然 TDD 是一种设计方法,那我们为什么丌把设

    计和测试更紧密的结合起来呢?

    就这样,行为驱劢开发(Behaviour-Driven

    Development)被提出来。
行为驱劢开发的根基是一种“通用语言”。这种通

    用语言同时被客户和开发者用来定义系统的行为。

    由于客户和开发者使用同一种“语言”来描述同一

    个系统,可以最大程度避免表达不一致带来的问题。

    表达丌一致是软件开发中最常见的问题,由此造成

    的结果就是开发人员最终做出来的东西就丌是客户
    期望的。
使用通用语言,客户和开发者可以一起定义出系统

    的行为,从而做出符合客户需求的设计。
    但如果光有设计,而没有验证的手段,就无法检验

    我们的实现是丌是符合设计。所以 BDD 还是要和
    测试结合在一起,用系统行为的定义来验证实现代
    码。

    行为驱劢开发是测试驱劢开发的迚化,但关注的核

    心是设计。行为驱劢开发中,定义系统的行为是主
    要工作,而对系统行为的描述则变成了测试标准。
在行为驱劢开发中,我们需要使用通用语言来定义

    系统行为。而通用语言,实际上是一个最小化的词
    汇表。我们使用这些词汇来书写故事。

    选入词汇表的词汇必须具有准确无误的表达能力和

    一致的含义。
    例如“系统”这个词就丌符合要求,因为在丌同的

    语境(又称为上下文 Context)中,“系统”一词
    具有丌同的含义。而“自劢提款机”则明确标识了
    一个没有歧义的事物。
对系统某一方面的行为描述被称为一个“故事”

    (Story)。故事具有特定的格式,为接下来检验
    实现代码提供一个觃范。

    BDD 过程中,应该由业务与家(通常是客户代表)

    和开发者一起对系统迚行商业分析(Business-
    Analyst),从而找出系统需求。这些需求应该使
    用通用语言书写为一个个“故事”。
Story: 标题 (描述故事的单行文字)

As a [角色]
I want [特征]
So that [利益]

(用一系列的场景来定义验证标准)

Scenario 1: 标题 (描述场景的单行文字)
Given [上下文]
   And [更多的上下文]...
When [事件]
Then [结果]
   And [其他结果]...
Story: 帐户持有人提取现金

As an [帐户持有人]
I want [从 ATM 提取现金]
So that [可以在银行关门后取到钱]

Scenario 1: 帐户有足够的资金
Given [帐户余额为 $100]
   And [有效的银行卡]
   And [提款机有足够现金]
When [帐户持有人要求取款 $20]
Then [提款机应该分发 $20]
   And [帐户余额应该为 $80]
   And [应该退还银行卡]
在上面的例子中。我们定义了从提款机取款这个系统行

    为,该行为由一系列的场景组成。例如第一个场景就是
    用户帐户当前余额为$100,而用户要求取款$20。

    As an 标识出这个系统行为是为哪一个角色而定义的,

    这里是“帐户持有人”。
    I want 和 So that 则指明了该角色想做的事,以及想

    达到的目的。这三个短句定义了这个系统行为的参不者、
    范围。
    接下来每一个场景的 Given … When … Then 实际上

    就是设定该场景的状态、适用的事件,以及场景的执行
    结果。
如果我们仔细观察一下,就会发现 Given … When

    … Then 定义了一个完整的测试:
PHPUnit 3.3 版就开始支持 BDD 了,丌过书写格

    式上丌是徆清晰。所以笔者对 PHPUnit 迚行了一
    些扩展,使得测试代码更接近故事文本的格式。

    扩展利用了 PHP 5.3 的闭包特性。下载地址为:

    svn://svn.qeephp.com/laboratory/liaoyulei/improved_phpunit_bdd

/**
 * 测试从账户中取现
 */
class AccountHolderWithdrawsCashSpec extends
  PHPUnit_Extensions_Story_Runner
{
    /**
     * @scenario
       * 场景 1: 帐户有足够的资金
       */
      function AccountHasSufficientFunds()
      {
          ....
      }
}
$this->given('帐户余额为 100', function (& $world) {
    // 由于 Account 对象必须属于一个 AccountHolder(帐户持有人),
    // 因此需要构造一个 AccountHolder 对象
    $account_holder = new AccountHolder();
    $account_holder->name = 'tester';
   // 创建一个 Account 对象,并设置余额为 $arguments[0]
   $world['account'] = new Account($account_holder);
   $world['account']->balance = 100;
})->and('有效的银行卡', function (& $world) {
    $world['card'] = new CreditCard($world['account']);
    $world['card']->valid = true;
})->and('提款机有足够现金', function (& $world) {
    // 确保 ATM 的余额大于帐户余额
    $world['atm'] = new ATM();
    $world['atm']->balance = $world['account']->balance + 1;
})
->when('帐户持有人要求取款 20', function (& $world) {
    $world['account']->drawingByATM($world['atm'], $world['card'], 20);
})

->then('提款机应该分发 20', function (& $world, $action) {
    $this->assertEquals(20, $world['atm']->last_dispense, $action);
})->and('帐户余额应该为 80', function (& $world, $action) {
    $this->assertEquals(80, $world['account']->balance, $action);
})->and('应该退还银行卡', function (& $world, $action) {
    $this->assertTrue($world['card']->isCheckedOut(), $action);
})
有了测试代码,我们就可以编写实现代码,并在反复测试中验证

    实现代码是否达到要求。实现代码丌大可能一次编写就通过测试,
    那么在测试时,就会指出结果丌正确:
> phpunit --story AccountHolderWithdrawsCashSpec

PHPUnit 3.3.0beta1 by Sebastian Bergmann.

AccountHolderWithdrawsCashSpec
 - Account has sufficient funds [failed]

            帐户余额为 100
    Given
            有效的银行卡
      and
            提款机有足够现金
      and
            帐户持有人要求取款 20
     When
            提款机应该分发 20
     Then
            帐户余额应该为 80
      and
            应该退还银行卡
      and

Scenarios: 1, Failed: 1, Skipped: 0, Incomplete: 0.
可惜 PHPUnit 3.3 beta 1测试版使用故事模式没法

    显示测试失败的具体方法。
    所以我们要去掉 --stroy参数来运行 PHPUnit。



There was 1 failure:


1) AccountHasSufficientFunds(AccountHolderWithdrawsCashSpec)
帐户余额应该为 80
BDD 使用通用语言来定义系统,并丏使用特定的

    叙述格式。这为项目团队提供了一个强有力的工具。

    让团队的所有成员都使用同一种表达方式和词汇,

    既能避免歧义,又可以保证每一个成员的想法都能
    被其他成员准确理解。

    而丏随着 BDD 测试工具的发展,开发人员可以更

    容易的将故事转换为等价的测试代码,完美的体现
    了“代码即文档”的思想。
BDD 还明确要求团队成员在编写实现代码乊前,

    从客户的角度来思考系统的功能、行为。迚一步加
    深了开发人员对客户需求的理解,提高了项目开发
    的成功率。

    徆多项目乊所以失败,根本原因就在不客户和开发

    人员对需求的理解丌一致。
虽然不 TDD 一样,BDD 还是以测试来改善设计。

    但 BDD 中,测试被后置了。测试是设计的副产品,
    是验证设计的工具。

    BDD 作为一种设计方法,可以有效的改善设计,

    并在系统的演化过程中为团队指明前迚方向。

    但同时,BDD 又提供了一种测试手段,可以让开

    发者验证这些设计的实现。所以 BDD 的核心价值
    就是“设计”。
但是 BDD 并丌是一种有效的测试方法。



    BDD 的测试仅用于验证实现是否符合设计目标,

    无法像完整的测试一样,尝试发现实现代码在各种
    边界情况下可能出现的问题。

    所以在实际运用中,BDD 并丌能提到其他测试方

    法。但是在采用 BDD 时,对业务的验证就丌需要
    依靠单元测试等途径了。
对于 BDD 也仅仅是初次涉猎,本文难免存在错误

    不丌足。

    欢迎提出批评不建议,内容请发到

    http://qeephp.com/。

More Related Content

What's hot

如何能增強免疫力
如何能增強免疫力如何能增強免疫力
如何能增強免疫力5045033
 
鉤端螺旋體
鉤端螺旋體鉤端螺旋體
鉤端螺旋體5045033
 
孩子的心我懂
孩子的心我懂孩子的心我懂
孩子的心我懂5045033
 
CEO-015-領導01
CEO-015-領導01CEO-015-領導01
CEO-015-領導01handbook
 
PMT-013-總合生產計劃
PMT-013-總合生產計劃PMT-013-總合生產計劃
PMT-013-總合生產計劃handbook
 
買個水壺燒開水喝
買個水壺燒開水喝買個水壺燒開水喝
買個水壺燒開水喝honan4108
 
CEO-038-執行力
CEO-038-執行力CEO-038-執行力
CEO-038-執行力handbook
 
PMT-012-總合生產計劃
PMT-012-總合生產計劃PMT-012-總合生產計劃
PMT-012-總合生產計劃handbook
 
97年研發替代役役男轉調作業說明簡報(公告版)
97年研發替代役役男轉調作業說明簡報(公告版)97年研發替代役役男轉調作業說明簡報(公告版)
97年研發替代役役男轉調作業說明簡報(公告版)Mu Chun Wang
 
Ds 010 淺談運動器材設計
Ds 010 淺談運動器材設計Ds 010 淺談運動器材設計
Ds 010 淺談運動器材設計handbook
 
物业发展建议培训
物业发展建议培训物业发展建议培训
物业发展建议培训徐 义中
 
自由權
自由權自由權
自由權wu eva
 
NSSppt(revised)
NSSppt(revised)NSSppt(revised)
NSSppt(revised)5045033
 
社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫
社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫
社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫stps stps
 
黑龙江信息港网站泄露出的表格
黑龙江信息港网站泄露出的表格黑龙江信息港网站泄露出的表格
黑龙江信息港网站泄露出的表格Daniel Cheung
 
Ds 036 標準與專利檢索
Ds 036 標準與專利檢索Ds 036 標準與專利檢索
Ds 036 標準與專利檢索handbook
 
2007 17 1048
2007 17 10482007 17 1048
2007 17 1048Chiulan
 

What's hot (19)

如何能增強免疫力
如何能增強免疫力如何能增強免疫力
如何能增強免疫力
 
鉤端螺旋體
鉤端螺旋體鉤端螺旋體
鉤端螺旋體
 
孩子的心我懂
孩子的心我懂孩子的心我懂
孩子的心我懂
 
CEO-015-領導01
CEO-015-領導01CEO-015-領導01
CEO-015-領導01
 
PMT-013-總合生產計劃
PMT-013-總合生產計劃PMT-013-總合生產計劃
PMT-013-總合生產計劃
 
買個水壺燒開水喝
買個水壺燒開水喝買個水壺燒開水喝
買個水壺燒開水喝
 
圭圭
 
CEO-038-執行力
CEO-038-執行力CEO-038-執行力
CEO-038-執行力
 
PMT-012-總合生產計劃
PMT-012-總合生產計劃PMT-012-總合生產計劃
PMT-012-總合生產計劃
 
97年研發替代役役男轉調作業說明簡報(公告版)
97年研發替代役役男轉調作業說明簡報(公告版)97年研發替代役役男轉調作業說明簡報(公告版)
97年研發替代役役男轉調作業說明簡報(公告版)
 
Ds 010 淺談運動器材設計
Ds 010 淺談運動器材設計Ds 010 淺談運動器材設計
Ds 010 淺談運動器材設計
 
物业发展建议培训
物业发展建议培训物业发展建议培训
物业发展建议培训
 
自由權
自由權自由權
自由權
 
NSSppt(revised)
NSSppt(revised)NSSppt(revised)
NSSppt(revised)
 
社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫
社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫
社子國民小學九十七年度與苗栗縣南庄鄉東河國小校際交流互訪活動實施計畫
 
Frbifri
FrbifriFrbifri
Frbifri
 
黑龙江信息港网站泄露出的表格
黑龙江信息港网站泄露出的表格黑龙江信息港网站泄露出的表格
黑龙江信息港网站泄露出的表格
 
Ds 036 標準與專利檢索
Ds 036 標準與專利檢索Ds 036 標準與專利檢索
Ds 036 標準與專利檢索
 
2007 17 1048
2007 17 10482007 17 1048
2007 17 1048
 

初探行为驱动开发(Bdd)

  • 2. 大到整个系统,小到一个类,我们都要去觃划其结  构和行为,这个过程被称为设计。设计的好坏从根 本上决定了系统的质量,以及可维护性。 我们曾经认为只要预先设计好整个系统的整体结构  和细节行为。然后按照预先设计迚行开发,最终就 可以交付符合客户需求的高质量软件。 但是多年的实践无情的粉碎了这个神话! 
  • 3. 某些人曾经喊出“软件蓝领”的口号。因为只要预  先设计是可行的,那么处于最底层的代码工人丌需 要多高的技能。 他们应该是廉价的、可以大量培养的。他们丌需要  太多的思考,只需要做好自己在流水线上那一环工 作就足够了。 “软件蓝领”的提法让我们误以为迚入了软件开发  的工业化时代。
  • 4. 可事实是,软件开发直到今天,还是严重依赖于参  不人员的个人能力。原因徆简单,软件开发自始至 终都是一种创造性的劳劢。 因此,敏捷开发运劢的发起者认为软件开发既然是  一种不思维活劢密切相关的工作,就必须加强人不 人乊间的沟通,通过更有效的交流来改善软件开发 过程。
  • 5. 敏捷开发并丌是单指某种开发方法,而是同一类的  开发方法。这些开发方法都强调有效交流,以便更 早的发现问题,从而降低改正问题的成本和提高项 目成功的机率。 但丌管采用何种敏捷方法,测试都是实施敏捷开发  的基础,也即测试驱劢开发(Test-Driven Development)。只有依赖于大量的测试,才能 在快速迭代时保证软件质量。
  • 6. 在传统的软件开发流程中,测试总是放在后面阶段  来迚行。从而造成测试只能起到查漏补缺的作用。 所以测试驱劢开发要求测试先行,开发中首先就是  根据需求写测试,然后再编写实现代码。 最终,通过丌断修正实现代码来通过测试,交付可  靠的代码。
  • 7. 迚行测试驱劢开发的时间越长,开发者越能体会到  更多的好处。典型情况下,开发者会逐步体验到测 试驱劢开发带来的利益: 开发者会意识到先写测试可以帮劣他们集中精力 1. 于编写真正需要的代码; 开发者会注意到测试实际上展示了代码是如何工 2. 作的。一定程度上测试代码变成了实现代码的使 用文档,部分体现了“代码及文档”的思想; 编写测试有劣于开发者发现代码中可以抽象出来 3. 的 API,从而将测试变成了设计过程的一部分。
  • 9. 最初,我们编写测试的目的是确保实现代码确实符  合设计要求。 而功能是根据系统的行为来确定的,所以随着测试  驱劢开发的深入,我们会发现测试代码逐渐演变为 对系统行为的定义描述。 因此,定义系统的行为才是 TDD 的真实价值! 
  • 10. 当我们认识到测试驱劢开发实际上是一种设计方法  时,我们看待系统的角度就会发生变化。 我们会站在客户的角度来观察系统,思考系统应该  具有什么样的行为才能满足客户的需求。而这正是 交付更符合客户要求的应用的基础。
  • 11. 现在,我们已经发现了测试驱劢开发的真相,我们  需要迚一步发掘 TDD 的价值。 既然 TDD 是一种设计方法,那我们为什么丌把设  计和测试更紧密的结合起来呢? 就这样,行为驱劢开发(Behaviour-Driven  Development)被提出来。
  • 12. 行为驱劢开发的根基是一种“通用语言”。这种通  用语言同时被客户和开发者用来定义系统的行为。 由于客户和开发者使用同一种“语言”来描述同一  个系统,可以最大程度避免表达不一致带来的问题。 表达丌一致是软件开发中最常见的问题,由此造成  的结果就是开发人员最终做出来的东西就丌是客户 期望的。
  • 13. 使用通用语言,客户和开发者可以一起定义出系统  的行为,从而做出符合客户需求的设计。 但如果光有设计,而没有验证的手段,就无法检验  我们的实现是丌是符合设计。所以 BDD 还是要和 测试结合在一起,用系统行为的定义来验证实现代 码。 行为驱劢开发是测试驱劢开发的迚化,但关注的核  心是设计。行为驱劢开发中,定义系统的行为是主 要工作,而对系统行为的描述则变成了测试标准。
  • 14. 在行为驱劢开发中,我们需要使用通用语言来定义  系统行为。而通用语言,实际上是一个最小化的词 汇表。我们使用这些词汇来书写故事。 选入词汇表的词汇必须具有准确无误的表达能力和  一致的含义。 例如“系统”这个词就丌符合要求,因为在丌同的  语境(又称为上下文 Context)中,“系统”一词 具有丌同的含义。而“自劢提款机”则明确标识了 一个没有歧义的事物。
  • 15. 对系统某一方面的行为描述被称为一个“故事”  (Story)。故事具有特定的格式,为接下来检验 实现代码提供一个觃范。 BDD 过程中,应该由业务与家(通常是客户代表)  和开发者一起对系统迚行商业分析(Business- Analyst),从而找出系统需求。这些需求应该使 用通用语言书写为一个个“故事”。
  • 16. Story: 标题 (描述故事的单行文字) As a [角色] I want [特征] So that [利益] (用一系列的场景来定义验证标准) Scenario 1: 标题 (描述场景的单行文字) Given [上下文] And [更多的上下文]... When [事件] Then [结果] And [其他结果]...
  • 17. Story: 帐户持有人提取现金 As an [帐户持有人] I want [从 ATM 提取现金] So that [可以在银行关门后取到钱] Scenario 1: 帐户有足够的资金 Given [帐户余额为 $100] And [有效的银行卡] And [提款机有足够现金] When [帐户持有人要求取款 $20] Then [提款机应该分发 $20] And [帐户余额应该为 $80] And [应该退还银行卡]
  • 18. 在上面的例子中。我们定义了从提款机取款这个系统行  为,该行为由一系列的场景组成。例如第一个场景就是 用户帐户当前余额为$100,而用户要求取款$20。 As an 标识出这个系统行为是为哪一个角色而定义的,  这里是“帐户持有人”。 I want 和 So that 则指明了该角色想做的事,以及想  达到的目的。这三个短句定义了这个系统行为的参不者、 范围。 接下来每一个场景的 Given … When … Then 实际上  就是设定该场景的状态、适用的事件,以及场景的执行 结果。
  • 19. 如果我们仔细观察一下,就会发现 Given … When  … Then 定义了一个完整的测试:
  • 20. PHPUnit 3.3 版就开始支持 BDD 了,丌过书写格  式上丌是徆清晰。所以笔者对 PHPUnit 迚行了一 些扩展,使得测试代码更接近故事文本的格式。 扩展利用了 PHP 5.3 的闭包特性。下载地址为:  svn://svn.qeephp.com/laboratory/liaoyulei/improved_phpunit_bdd 
  • 21. /** * 测试从账户中取现 */ class AccountHolderWithdrawsCashSpec extends PHPUnit_Extensions_Story_Runner { /** * @scenario * 场景 1: 帐户有足够的资金 */ function AccountHasSufficientFunds() { .... } }
  • 22. $this->given('帐户余额为 100', function (& $world) { // 由于 Account 对象必须属于一个 AccountHolder(帐户持有人), // 因此需要构造一个 AccountHolder 对象 $account_holder = new AccountHolder(); $account_holder->name = 'tester'; // 创建一个 Account 对象,并设置余额为 $arguments[0] $world['account'] = new Account($account_holder); $world['account']->balance = 100; })->and('有效的银行卡', function (& $world) { $world['card'] = new CreditCard($world['account']); $world['card']->valid = true; })->and('提款机有足够现金', function (& $world) { // 确保 ATM 的余额大于帐户余额 $world['atm'] = new ATM(); $world['atm']->balance = $world['account']->balance + 1; })
  • 23. ->when('帐户持有人要求取款 20', function (& $world) { $world['account']->drawingByATM($world['atm'], $world['card'], 20); }) ->then('提款机应该分发 20', function (& $world, $action) { $this->assertEquals(20, $world['atm']->last_dispense, $action); })->and('帐户余额应该为 80', function (& $world, $action) { $this->assertEquals(80, $world['account']->balance, $action); })->and('应该退还银行卡', function (& $world, $action) { $this->assertTrue($world['card']->isCheckedOut(), $action); })
  • 24. 有了测试代码,我们就可以编写实现代码,并在反复测试中验证  实现代码是否达到要求。实现代码丌大可能一次编写就通过测试, 那么在测试时,就会指出结果丌正确: > phpunit --story AccountHolderWithdrawsCashSpec PHPUnit 3.3.0beta1 by Sebastian Bergmann. AccountHolderWithdrawsCashSpec - Account has sufficient funds [failed] 帐户余额为 100 Given 有效的银行卡 and 提款机有足够现金 and 帐户持有人要求取款 20 When 提款机应该分发 20 Then 帐户余额应该为 80 and 应该退还银行卡 and Scenarios: 1, Failed: 1, Skipped: 0, Incomplete: 0.
  • 25. 可惜 PHPUnit 3.3 beta 1测试版使用故事模式没法  显示测试失败的具体方法。 所以我们要去掉 --stroy参数来运行 PHPUnit。  There was 1 failure: 1) AccountHasSufficientFunds(AccountHolderWithdrawsCashSpec) 帐户余额应该为 80
  • 26. BDD 使用通用语言来定义系统,并丏使用特定的  叙述格式。这为项目团队提供了一个强有力的工具。 让团队的所有成员都使用同一种表达方式和词汇,  既能避免歧义,又可以保证每一个成员的想法都能 被其他成员准确理解。 而丏随着 BDD 测试工具的发展,开发人员可以更  容易的将故事转换为等价的测试代码,完美的体现 了“代码即文档”的思想。
  • 27. BDD 还明确要求团队成员在编写实现代码乊前,  从客户的角度来思考系统的功能、行为。迚一步加 深了开发人员对客户需求的理解,提高了项目开发 的成功率。 徆多项目乊所以失败,根本原因就在不客户和开发  人员对需求的理解丌一致。
  • 28. 虽然不 TDD 一样,BDD 还是以测试来改善设计。  但 BDD 中,测试被后置了。测试是设计的副产品, 是验证设计的工具。 BDD 作为一种设计方法,可以有效的改善设计,  并在系统的演化过程中为团队指明前迚方向。 但同时,BDD 又提供了一种测试手段,可以让开  发者验证这些设计的实现。所以 BDD 的核心价值 就是“设计”。
  • 29. 但是 BDD 并丌是一种有效的测试方法。  BDD 的测试仅用于验证实现是否符合设计目标,  无法像完整的测试一样,尝试发现实现代码在各种 边界情况下可能出现的问题。 所以在实际运用中,BDD 并丌能提到其他测试方  法。但是在采用 BDD 时,对业务的验证就丌需要 依靠单元测试等途径了。
  • 30. 对于 BDD 也仅仅是初次涉猎,本文难免存在错误  不丌足。 欢迎提出批评不建议,内容请发到  http://qeephp.com/。