Writing runnable acceptance criteria in plain text with<br />Farooq Ali<br />
The Yawning<br />Crevasse of Doom<br />
fluffy high-level needs<br />
<technical_babble /><br />
[Test]<br />[ExpectedException(typeof(InsufficientFundsException))]<br />public void TransferWithInsufficientFunds()<br />...
the convergence of two movements<br />
the convergence of two movements<br />Behavior-Driven Development  (BDD)<br />& Domain-Specific Languages (DSLs)<br />
“Acceptance criteria <br />should be executable”<br />“…a ubiquitous <br />language for analysis”<br />BDD movement<br />
what are we really trying to describe?<br />
what are we really trying to describe?<br />the human concept of causality<br />
Causality<br />Precondition 	-> 	Given<br />           Action		-> 	When<br />      Outcome		-> 	Then<br />
Causality<br />Setup Data/State 	-> 	Given<br />        Call Method	-> 	When<br />      	   Assert	 	-> 	Then<br />
“…a computer language that's targeted <br />to a particular kind of problem, rather <br />than a general purpose language ...
“The sweet spot, however is in making <br />DSLs business-readable rather than <br />business-writeable.”<br />DSL movemen...
BDD + DSL<br />
Gherkin<br />Feature: Addition<br />As a math moron<br />I want to add two numbers together<br />So that I can better use ...
Acceptance Criteria<br />
Shared Vocabulary<br />
Documentation<br />
Traceability<br />
Bug Tracking<br />
Using Cucumber<br />
Components<br />Building Blocks<br />Acceptance Criteria<br />(Plain Text)<br />Step Definitions<br />(Ruby)<br />
Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers to...
Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers to...
Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers to...
Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers to...
Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers to...
Keywords<br />Keywords<br />
Languages<br />Languages<br />Macintosh-9:calculator ThoughtWorks$ cucumber --language help<br />| ar     | Arabic        ...
Step Definitions<br />Building Blocks<br />Given I enter 1 into the calculatorWhen I add 1 to itThen the calculator should...
Step Definitions<br />Building Blocks<br />Given I enter 1 into the calculatorWhen I add 1 to itThen the calculator should...
Step Definitions<br />Step Definitions<br />Given /^I enter (.+) into the calculator$/ do |number|@calculator = Calculator...
Step Definitions<br />Step Definitions<br />Then /^the calculator should show (.+)$/ do |number|@calculator.number.should ...
Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />
Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />
Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />/I give a (d+)-m...
Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />/I give a (d+)-m...
Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />/I give a (d+)-m...
Multiple Given-When-Thens<br />Scenario: Multiple Givens<br />    Given one thing<br />    Given another thing<br />    Gi...
Or use And / But<br />Scenario: Multiple Givens<br />    Given one thing <br />And another thing <br />And yet another thi...
Reuse<br />Calling steps from within steps<br />Given /^the user (.*) exists$/ do |name|#...<br />end<br />Given /^I log i...
Reuse<br />Multiline step arguments - Tables<br />Given the following people exist:<br />  | name   | email            | p...
Reuse<br />Multiline step arguments - Tables<br />Given the following people exist:<br />  | name   | email            | p...
Reuse<br />Multiline step arguments - Strings<br />Given a blog post named "Random" with Markdown body<br />  """<br />  S...
Reuse<br />Multiline step arguments - Strings<br />Given a blog post named "Random" with Markdown body<br />  """<br />  S...
Tags<br />Tags<br />@billingFeature: Enter billing info@creditcardScenario: Credit card <br />	  @paypal<br />  Scenario: ...
Hooks<br />Hooks<br />Before do# do something before first step of scenarioendAfter do# do something after each scenarioen...
Tagged Hooks<br />Tagged Hooks<br />Before('@billing', '@calculations') do # This will only run before scenarios tagged<br...
Global Hooks<br />Global Hooks<br />browser = Selenium::SeleniumDriver.new("localhost", 4444, "*chrome", <br />										 ...
Tags<br />Backgrounds<br />Feature: Multiple site support<br />  As a Mephisto site owner<br />  I want to host blogs for ...
Global Hooks<br />Step Argument Transforms<br /># support file<br />Transform /^user (w+)$/ do |username|<br />User.find_b...
Formatters<br />cucumber -fjunit -–out <output_dir><br />
Formatters: Steps<br />Feature: --formatter steps option - Steps Formatter  In order to easily see which steps are already...
Formatters : JUnit<br />Feature: JUnit output formatter<br />  In order for developers to create test reports with ant<br ...
Formatters : HTML<br />Feature: HTML formatter<br />  In order to make it easy to read Cucumber results<br />  there shoul...
Upcoming SlideShare
Loading in …5
×

Cucumber

5,557 views

Published on

Writing runnable acceptance criteria in plain text with Cucumber.

Published in: Technology
2 Comments
2 Likes
Statistics
Notes
No Downloads
Views
Total views
5,557
On SlideShare
0
From Embeds
0
Number of Embeds
30
Actions
Shares
0
Downloads
64
Comments
2
Likes
2
Embeds 0
No embeds

No notes for slide
  • This is something that developers who test are very familiar with from unit testing
  • This is something that developers who test are very familiar with from unit testing
  • ericevans ubiquitous language
  • over 30 spoken languages show languages.yml
  • demonstrate use of cucumber –tags @arithmetic
  • demonstrate use of cucumber –tags @arithmetic
  • Cucumber

    1. 1. Writing runnable acceptance criteria in plain text with<br />Farooq Ali<br />
    2. 2. The Yawning<br />Crevasse of Doom<br />
    3. 3. fluffy high-level needs<br />
    4. 4. <technical_babble /><br />
    5. 5. [Test]<br />[ExpectedException(typeof(InsufficientFundsException))]<br />public void TransferWithInsufficientFunds()<br />{<br /> Account source = new Account();<br /> source.Deposit(200.00F);<br /> Account destination = new Account();<br /> destination.Deposit(150.00F);<br />}<br />
    6. 6.
    7. 7. the convergence of two movements<br />
    8. 8. the convergence of two movements<br />Behavior-Driven Development (BDD)<br />& Domain-Specific Languages (DSLs)<br />
    9. 9. “Acceptance criteria <br />should be executable”<br />“…a ubiquitous <br />language for analysis”<br />BDD movement<br />
    10. 10. what are we really trying to describe?<br />
    11. 11. what are we really trying to describe?<br />the human concept of causality<br />
    12. 12. Causality<br />Precondition -> Given<br /> Action -> When<br /> Outcome -> Then<br />
    13. 13. Causality<br />Setup Data/State -> Given<br /> Call Method -> When<br /> Assert -> Then<br />
    14. 14. “…a computer language that's targeted <br />to a particular kind of problem, rather <br />than a general purpose language that's <br />aimed at any kind of software problem.”<br />DSL movement<br />
    15. 15. “The sweet spot, however is in making <br />DSLs business-readable rather than <br />business-writeable.”<br />DSL movement<br />
    16. 16. BDD + DSL<br />
    17. 17. Gherkin<br />Feature: Addition<br />As a math moron<br />I want to add two numbers together<br />So that I can better use my scarce brain processing power<br />Scenario: Adding positive numbers together<br />Given I enter 1 into the calculator<br />When I add 1 to it<br />Then the calculator should show 2<br />
    18. 18. Acceptance Criteria<br />
    19. 19. Shared Vocabulary<br />
    20. 20. Documentation<br />
    21. 21. Traceability<br />
    22. 22. Bug Tracking<br />
    23. 23. Using Cucumber<br />
    24. 24. Components<br />Building Blocks<br />Acceptance Criteria<br />(Plain Text)<br />Step Definitions<br />(Ruby)<br />
    25. 25. Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers together<br />So that I can better use my scarce brain processing power<br /> Scenario: Adding positive numbers together<br /> Given I enter 1 into the calculator<br /> When I add 1 to it<br /> Then the calculator should show 2<br />
    26. 26. Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers together<br />So that I can better use my scarce brain processing power<br /> Scenario: Adding positive numbers together<br /> Given I enter 1 into the calculator<br /> When I add 1 to it<br /> Then the calculator should show 2<br />
    27. 27. Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers together<br />So that I can better use my scarce brain processing power<br /> Scenario: Adding positive numbers together<br /> Given I enter 1 into the calculator<br /> When I add 1 to it<br /> Then the calculator should show 2<br />
    28. 28. Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers together<br />So that I can better use my scarce brain processing power<br />Scenario: Adding positive numbers together<br /> Given I enter 1 into the calculator<br /> When I add 1 to it<br /> Then the calculator should show 2<br />
    29. 29. Acceptance Criteria<br />Acceptance Criteria<br />Feature: Addition<br />As a math moron<br />I want to add two numbers together<br />So that I can better use my scarce brain processing power<br /> Scenario: Adding positive numbers together<br />Given I enter 1 into the calculator<br />When I add 1 to it<br />Then the calculator should show 2<br />
    30. 30. Keywords<br />Keywords<br />
    31. 31. Languages<br />Languages<br />Macintosh-9:calculator ThoughtWorks$ cucumber --language help<br />| ar | Arabic | العربية<br />| bg | Bulgarian | български<br />| cat | Catalan | català<br />| cy | Welsh | Cymraeg<br />| cz | Czech | Česky<br />| da | Danish | dansk<br />| de | German | Deutsch <br />| en | English | English <br />| en-au | Australian | Australian <br />| en-lol | LOLCAT | LOLCAT <br />| en-tx | Texan | Texan <br />| es | Spanish | español<br />| et | Estonian | eesti keel <br />| fi | Finnish | suomi<br />| fr | French | français<br />| he | Hebrew | עברית<br />| hr | Croatian | hrvatski<br />| hu | Hungarian | magyar<br />| id | Indonesian | Bahasa Indonesia<br />
    32. 32. Step Definitions<br />Building Blocks<br />Given I enter 1 into the calculatorWhen I add 1 to itThen the calculator should show 2<br />Acceptance Criteria<br />(Plain Text)<br />
    33. 33. Step Definitions<br />Building Blocks<br />Given I enter 1 into the calculatorWhen I add 1 to itThen the calculator should show 2<br />Acceptance Criteria<br />(Plain Text)<br />Given /^I enter (.+) into the calculator$/ do |number|@calculator = Calculator.new@calculator.enter(number.to_i)endWhen /^I add (.+) to it$/ do |number|@calculator.add(number.to_i)endWhen /^the calculator should show (.+)$/ do |number|@calculator.number.should == number.to_iend<br />Step Definitions<br />(Ruby)<br />
    34. 34. Step Definitions<br />Step Definitions<br />Given /^I enter (.+) into the calculator$/ do |number|@calculator = Calculator.new@calculator.enter(number.to_i)endWhen /^I add (.+) to it$/ do |number|@calculator.add(number.to_i)endThen /^the calculator should show (.+)$/ do |number|@calculator.number.should == number.to_iend<br />
    35. 35. Step Definitions<br />Step Definitions<br />Then /^the calculator should show (.+)$/ do |number|@calculator.number.should == number.to_iend<br />
    36. 36. Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />
    37. 37. Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />
    38. 38. Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />/I give a (d+)-minute long talk on (.+) at (d+):(d+)(am|pm)/<br />
    39. 39. Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />/I give a (d+)-minute long talk on (.+) at (d+):(d+)(am|pm)/<br />
    40. 40. Step Definitions<br />Step Definitions<br />When I give a 45-minute long talk on Cucumber at 10:30am<br />/I give a (d+)-minute long talk on (.+) at (d+):(d+)(am|pm)/<br />do |duration_in_minutes, topic, start_hour, start_minute, am_pm|end<br />
    41. 41. Multiple Given-When-Thens<br />Scenario: Multiple Givens<br /> Given one thing<br /> Given another thing<br /> Given yet another thing<br /> When I open my eyes<br /> Then I see something<br /> Then I don't see something else<br />Multiple Given-When-Thens<br />
    42. 42. Or use And / But<br />Scenario: Multiple Givens<br /> Given one thing <br />And another thing <br />And yet another thing<br /> When I open my eyes<br /> Then I see something<br />But I don't see something else<br />Or use And/But<br />
    43. 43. Reuse<br />Calling steps from within steps<br />Given /^the user (.*) exists$/ do |name|#...<br />end<br />Given /^I log in as (.*)$/ do |name|<br /> #...<br />end<br />Given /^(.*) is logged in$/ do |name|<br /> Given "the user #{name} exists"<br /> Given "I log in as #{name}"<br />end<br />
    44. 44. Reuse<br />Multiline step arguments - Tables<br />Given the following people exist:<br /> | name | email | phone |<br /> | Farooq | farooq@email.com | 123 |<br /> | Mary | mary@email.com | 234 |<br /> | Bob | bob@email.org | 456 |<br />
    45. 45. Reuse<br />Multiline step arguments - Tables<br />Given the following people exist:<br /> | name | email | phone |<br /> | Farooq | farooq@email.com | 123 |<br /> | Mary | mary@email.com | 234 |<br /> | Bob | bob@email.org | 456 |<br />Given /the following people exist:/ do |people_table|people_table.hashes.each do |hash|# 1st: {'name' => ’Farooq', 'email' => ’farooq@email.com’, ... } # 2nd: {'name' => ’Mary', 'email' => ’mary@email.com', ... } # ...endend<br />
    46. 46. Reuse<br />Multiline step arguments - Strings<br />Given a blog post named "Random" with Markdown body<br /> """<br /> Some Title, Eh?<br /> ==============<br /> Here is the first paragraph of my blog post. Loremipsum dolor sit amet,<br />consecteturadipiscingelit.<br /> """<br />
    47. 47. Reuse<br />Multiline step arguments - Strings<br />Given a blog post named "Random" with Markdown body<br /> """<br /> Some Title, Eh?<br /> ==============<br /> Here is the first paragraph of my blog post. Loremipsum dolor sit amet,<br />consecteturadipiscingelit.<br /> """<br />Given /^a blog post named "([^"]*)" with Markdown body$/ do |title, markdown|Post.create!(:title=> title, :body => markdown)end<br />
    48. 48. Tags<br />Tags<br />@billingFeature: Enter billing info@creditcardScenario: Credit card <br /> @paypal<br /> Scenario: PayPal<br />
    49. 49. Hooks<br />Hooks<br />Before do# do something before first step of scenarioendAfter do# do something after each scenarioend<br />
    50. 50. Tagged Hooks<br />Tagged Hooks<br />Before('@billing', '@calculations') do # This will only run before scenarios tagged<br /> # with @billing or @calculations. <br />end<br />
    51. 51. Global Hooks<br />Global Hooks<br />browser = Selenium::SeleniumDriver.new("localhost", 4444, "*chrome", <br /> "http://localhost", 15000)<br />Given 'I am on the Google search page' do<br />browser.open('http://www.google.com/’)<br />end<br />When /I search for "(.*)"/ do |query|<br />browser.type('q', query) <br />browser.click 'btnG’<br />browser.wait_for_page_to_load<br />end<br />Then /I should see a link to (.*)/ do |expected_url|<br />browser.is_element_present("css=a[href='#{expected_url}']").should be_true<br />end<br />
    52. 52. Tags<br />Backgrounds<br />Feature: Multiple site support<br /> As a Mephisto site owner<br /> I want to host blogs for different people<br /> In order to make gigantic piles of money <br />Background: <br /> Given a global administrator named “Greg” <br /> And a blog named “Greg’s anti-tax rants” <br /> And a customer named “Dr. Bill” <br /> And a blog named “Expensive Therapy” owned by “Dr. Bill” <br />Scenario: Dr. Bill posts to his own blog <br /> Given I am logged in as Dr. Bill <br /> When I try to post to “Expensive Therapy”<br /> Then I should see “Your article was published.” <br />
    53. 53. Global Hooks<br />Step Argument Transforms<br /># support file<br />Transform /^user (w+)$/ do |username|<br />User.find_by_username(username) <br />end<br /># step definition file<br />Then /^(user w+) should be friends with (user w+)$/ do |user,friend| <br />user.shouldbe_friends_with(friend)<br />end<br />
    54. 54. Formatters<br />cucumber -fjunit -–out <output_dir><br />
    55. 55. Formatters: Steps<br />Feature: --formatter steps option - Steps Formatter In order to easily see which steps are already defined, specially when using 3rd party steps libraries, Cucumber should show the available steps in a user-friendly format Background: Given I am in steps_library Scenario: Printing steps When I run cucumber -f steps features Then it should pass with """ features/step_definitions/steps_lib1.rb /^I defined a first step$/ # features/step_definitions/steps_lib1.rb:1 /^I define a second step$/ # features/step_definitions/steps_lib1.rb:4 /^I should also have a third step$/ # features/step_definitions/steps_lib1.rb:7 features/step_definitions/steps_lib2.rb /^I defined a step 4$/ # features/step_definitions/steps_lib2.rb:1 /^I create a step 5$/ # features/step_definitions/steps_lib2.rb:4 /^I should be too tired for step 6$/ # features/step_definitions/steps_lib2.rb:7 6 step definition(s) in 2 source file(s). """<br />
    56. 56. Formatters : JUnit<br />Feature: JUnit output formatter<br /> In order for developers to create test reports with ant<br /> Cucumber should be able to output JUnit xml files<br /> Background:<br /> Given I am in junit<br /> And the tmp directory is empty<br /> @mri186<br /> Scenario: one feature, one passing scenario, one failing scenario<br /> When I run cucumber --format junit --out tmp/ features/one_passing_one_failing.feature<br /> Then it should fail with<br /> """<br /> """<br /> And "examples/junit/tmp/TEST-one_passing_one_failing.xml" with junit duration "0.005" should contain<br /> """<br /> <?xml version="1.0" encoding="UTF-8"?><br /> <testsuite errors="0" failures="1" name="One passing scenario, one failing scenario" tests="2" time="0.005"><br /> <testcaseclassname="One passing scenario, one failing scenario.Passing" name="Passing" time="0.005"><br /> </testcase><br /> <testcaseclassname="One passing scenario, one failing scenario.Failing" name="Failing" time="0.005"><br /> <failure message="failed Failing" type="failed"><br /> Scenario: Failing<br /> Given a failing scenario<br /> Message:<br /> (RuntimeError)<br /> features/one_passing_one_failing.feature:7:in `Given a failing scenario' </failure><br /> </testcase><br /> </testsuite><br /> """<br /> Scenario: pending steps are simply skipped<br /> When I run cucumber --format junit --out tmp/ features/pending.feature<br /> Then it should pass with<br /> """<br /> """<br /> And "examples/junit/tmp/TEST-pending.xml" with junit duration "0.009" should contain<br /> """<br /> <?xml version="1.0" encoding="UTF-8"?><br /> <testsuite errors="0" failures="0" name="Pending step" tests="0" time="0.009"><br /> </testsuite><br /> """<br /> Scenario: pending step with strict option should fail<br /> When I run cucumber --format junit --out tmp/ features/pending.feature --strict<br /> Then it should fail with<br /> """<br /> """<br /> And "examples/junit/tmp/TEST-pending.xml" with junit duration "0.000160" should contain<br /> """<br /> <?xml version="1.0" encoding="UTF-8"?><br /> <testsuite errors="0" failures="1" name="Pending step" tests="1" time="0.000160"><br /> <testcaseclassname="Pending step.Pending" name="Pending" time="0.000160"><br /> <failure message="pending Pending" type="pending"><br /> Scenario: Pending<br /> TODO (Cucumber::Pending)<br /> features/pending.feature:4:in `Given a pending step' </failure><br /> </testcase><br /> </testsuite><br /> """<br /> Scenario: run all features<br /> When I run cucumber --format junit --out tmp/ features<br /> Then it should fail with<br /> """<br /> """<br /> And "examples/junit/tmp/TEST-one_passing_one_failing.xml" should exist<br /> And "examples/junit/tmp/TEST-pending.xml" should exist<br /> Scenario: show correct error message if no --out is passed<br /> When I run cucumber --format junit features<br /> Then STDERR should not match <br /> """<br />can't convert .* into String (TypeError)<br /> """<br /> And STDERR should match<br /> """<br />You *must* specify --out DIR for the junit formatter<br /> """<br />
    57. 57. Formatters : HTML<br />Feature: HTML formatter<br /> In order to make it easy to read Cucumber results<br /> there should be a HTML formatter with an awesome CSS<br /> Scenario: Everything in examples/self_test<br /> When I run cucumber -q --format html --out tmp/a.html features<br /> Then "examples/self_test/tmp/a.html" should have the same contents as "features/html_formatter/a.html"<br />

    ×