在刚接触BDD(Behavior Driven Development,行为驱动开发)的时候,我以为是用Cucumber这样的工具来编写场景用例,从而实现自动化测试,甚至很长时间分不清BDD和ATDD(Acceptance test driven development)到底有什么区别。那么,BDD真的是用来做自动化测试的吗?本文来跟大家分享一下我理解的BDD。
  为什么要BDD?
  “开发软件系统困难的部分是准确说明开发什么” (“The hardest single part of building a software system is deciding precisely what to build” — No Silver Bullet, Fred Brooks) 。
  场景一:业务分析人员觉得自己分析的需求已经写的很清晰了,并且跟技术人员进行了足够的沟通,可是开发完sign off的时候,发现所开发的功能还是跟期望有差距。
  场景二:开发团队辛辛苦苦开发完一个功能,满怀信心的去给客户展示的时候,才发现原来客户需求的功能不是这样的。
  这些场景是不是似曾相识?为什么会这样?第一个场景是开发团队内部技术人员跟需求分析人员的理解有偏差,导致大家理解的需求其实是不一样的;第二个场景是开发团队没有真正理解产品经理/客户所提出来的真实需求,导致开发的产品跟需求不一致。其实,产生这两个不一致的真正原因是因为不同角色有着不同的领域知识,说着不同的语言,大家在沟通的时候,如果都用自己领域语言,必然会产生沟通代沟,导致理解的不一致性。
  领域知识不同、语言不通导致沟通障碍,这个客观存在的问题该如何解决呢?BDD正是为此而生。
  BDD是什么?
  BDD的提出者Dan North强调BDD不是关于测试的,它是在应用程序存在之前,写出用例与期望,从而描述应用程序的行为,并且促使在项目中的人们彼此互相沟通。
  要给BDD下个清晰易懂的定义很难,包括大师们也这么认为,这里试着总结以下几点:
  关注的是业务领域,而不是技术:BDD强调用领域特定语言(DSL, domain specific language)描述用户行为,定义业务需求,而不会关心系统的技术实现。
  不是工具,强调的是一种协作方式:BDD要求各个角色共同参与系统行为的挖掘和定义,以实现对业务价值的一致理解。
  不是关于测试的:BDD源自TDD,但重点不是关于测试,所强调的沟通与协作可以指导更好的做自动化测试。
  全栈敏捷方法:BDD促使团队所有角色从需求到后的测试验证,进行高度的协作和沟通,以交付有价值的功能。
  BDD怎么做?
  用例场景的描述格式“GIVEN… WHEN… THEN… ”对大家都不陌生,但用这个格式写出好的用例却是非常的难,尤其是新手。这里总结几点供大家参考:
  1.业务层抽取,业务语言描述
  根据业务层的数据流,在每个数据停留点进行纵切,抽取出一个个用例场景。描述语言一定是业务领域可懂的,不要涉及任何实现相关的技术细节。所描述的场景一定是从业务层抽象出来,体现真实业务价值的。
  2.技术人员可懂,自动化友好
  所描述的用例场景要能驱动开发,必须要让技术人员易于理解;要指导自动化测试,还得要求对于自动化的实现是友好的。这一点似乎是跟第一点有些矛盾,但我们严格遵守BDD的格式要求还是可以做到的。其中,GIVEN从句描述的是场景的前提条件、初始状态,通常是一种现在完成时态;WHEN从句是采取某个动作或者是发生某个事件,一定是动词,通常是一般现在时;THEN从句用“应该…(should be…)”来描述一种期望的结果,而不用断言(assert),后者与测试关联更紧密。
  3.数据驱动,需求实例化
  抽象的业务语言描述的需求,往往由于太抽象而缺失掉很多关键信息,导致不同人员对需求理解的不一致。想要既抽象又能包含细节信息,需要采用需求实例来描述。简单说来,是给场景用例举例说明。举例会需要列举数据,如果在场景用例描述里边直接添加数据实例,那样的用例将会很混乱,可读性和可维护性都非常差。如果我们能够在描述场景的用例里边用一些变量来代替,把变量对应的值(数据)提取出来存为一个表格或者独立的文件,这样将会使得用例的可读性很好,而且也不会缺失细节信息(数据),后期的维护和修改也较为方便。这是数据驱动的方法来描述实例化的需求。
  看几个例子,大家体会一下:
  场景一:检查收件箱,可以看出第三个清晰明了且能体现业务价值,比较符合上面的要求。
  Scenario: Check Inbox
  Given a user "Tom" with password "123"
  And a user "Jerry" with password "abc"
  And an email to "Tom" from "Jerry"
  When I sign in as "Tom" with password "123"
  Then I should see one email from "Jerry" in my inbox
  Scenario: Check Inbox
  Given a user "Tom"
  And a user "Jerry"
  And an email to "Tom" from "Jerry"
  When I sign in as "Tom"
  Then I should see one email from "Jerry" in my inbox
  Scenario: Check Inbox
  Given I have received an email from "Jerry"
  When I sign in
  Then I should see one email from "Jerry" in my inbox
  场景二:限制非法用户查看某些受限内容,BDD强调什么(What),而不是怎么(How),第二个写的比较好。
  Scenario: Redirect user to originally requested page after logging in
  Given a user "Tom" exists with password "123"
  And I am not logged in
  When I navigate to the home page
  Then I am redirected to the login form
  When I fill in "Username" with "tom"
  And I fill in "Password" with "123"
  And I press "Login"
  Then I should be on the home page
  Scenario: Redirect user to originally requested page after logging in
  Given I am an unauthenticated user
  When I attempt to view some restricted content
  Then I am shown a login form
  When I authenticate with valid credentials
  Then I should be shown the restricted content
  场景三:添加图书到购物车并计算总额
  Scenario: Books add to shopping cart with correct number and total price
  Given a book "BDD" with price "30.5"
  And a book "Cucumber" with price "25.8"
  When I select "BDD"
  And I click the add to shopping cart button
  Then I should see one "BDD" in my shopping cart
  And the total price is "30.5"
  When I select "Cucumber"
  And I click the add to shopping cart button twice
  Then I should see two books "Cucumber" in my shopping cart
  And the total price is "82.1"
  Scenario Outline: Books add to shopping cart with correct number and total price
  Given book <name1> with <price1>
  And book <name2> with <price2>
  When I add <number1> book <name1> and <number2> book <name2> to shopping cart
  Then I should see book <name1> and <name2> in my shopping cart
  And the total price should be <total>
  Examples:
  | name1    | price1 | number1 | name2    | price2 | number2 | total |
  | BDD      | 30.5   | 1       | -        | -      | -       | 30.5  |
  | Cucumber | 25.8   | 2       | -        | -      | -       | 51.6  |
  | BDD      | 30.5   | 1       | Cucumber | 25.8   | 2       | 82.1  |
  BDD的工具有Cucumber、JBehave、Twist、Concordion等,工具的优缺点和使用方法,网上都有丰富的文档可参考,在此不作介绍。