Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Story Driven Development With Cucumber

12,899 views

Published on

Software projects are rarely on-spec, on-time and on-budget, and the primary cause is miscommunication. As Martin Fowler says, there is a "yawning crevasse of doom" between stakeholders and developers, full of misunderstanding. How do you make sure that you're building something that adds value? How do you know you're building the thing that was asked for? How does your bottom line affect user experience?

Into the fray leaps Cucumber, a business-readable DSL combined with an awesome Ruby library that lets domain experts express business requirements as executable user stories. We'll cover outside-in, story-driven development with Cucumber, how to write effective stories, and how to make Cucumber work for your project.

(as given to CharlotteRuby on Jan 6, 2010)

Published in: Technology

Story Driven Development With Cucumber

  1. 1. Story-Driven Development with Cucumber Sean Cribbs
  2. 2. who am i • Freelance Web Consultant • Radiant Lead Dev • Ruby, Javascript, Erlang • Open-source contributor github.com/seancribbs
  3. 3. miscommunication
  4. 4. abstract
  5. 5. what’s important
  6. 6. who said what
  7. 7. miscommunication = waste
  8. 8. wrong
  9. 9. incorrectly
  10. 10. unnecessarily
  11. 11. “Agile”
  12. 12. user stories
  13. 13. Test-Driven Development
  14. 14. Story-Driven Development
  15. 15. stay lean create value
  16. 16. minimum to satisfy
  17. 17. make, protect, save money
  18. 18. pop the “why”stack
  19. 19. who are the stakeholders?
  20. 20. improves communication
  21. 21. bridge the crevasse of doom
  22. 22. living functional spec
  23. 23. stories = tests
  24. 24. http://cukes.info/
  25. 25. business-readable DSL
  26. 26. a Ruby library
  27. 27. integration tests
  28. 28. Feature: Standard Signup In order to begin using the application As a new user I want to create an account Scenario: Signup with valid email/password combination Given I do not have an account When I signup with email and password Then I should be logged in And my profile details should be filled in
  29. 29. Feature: Standard Signup In order to begin using the application As a new user I want to create an account Scenario: Signup with valid email/password combination Given I do not have an account When I signup with email and password Then I should be logged in And my profile details should be filled in
  30. 30. $ cucumber Feature: Standard Signup In order to begin using the application As a new user I want to create an account Scenario: Signup with valid email/password combination Given I do not have an account When I signup with email and password Then I should be logged in And my profile details should be filled in 1 scenario (1 undefined) 4 steps (4 undefined) 0m0.754s
  31. 31. You can implement step definitions for undefined steps with these snippets: Given /^I do not have an account$/ do pending end When /^I signup with email and password$/ do pending end Then /^I should be logged in$/ do pending end Then /^my profile details should be filled in$/ do pending end
  32. 32. Given /^I do not have an account$/ do User.count.should == 0 end
  33. 33. Feature: Standard Signup In order to begin using the application As a new user I want to create an account Scenario: Signup with valid email/password combination Given I do not have an account uninitialized constant User (NameError) ./features/step_definitions/signup_steps.rb:2:in `/^I do not have an account$/' features/signup.feature:7:in `Given I do not have an account' When I signup with email and password Then I should be logged in And my profile details should be filled in Failing Scenarios: cucumber features/signup.feature:6 # Scenario: Signup with valid email/ password combination 1 scenario (1 failed) 4 steps (1 failed, 3 undefined) 0m0.136s
  34. 34. $ script/generate model User email:string password:string exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/user.rb create test/unit/user_test.rb create test/fixtures/users.yml create db/migrate create db/migrate/20090912024901_create_users.rb $ rake db:migrate db:test:prepare == CreateUsers: migrating ========================= -- create_table(:users) -> 0.0016s == CreateUsers: migrated (0.0017s) ================
  35. 35. Feature: Standard Signup In order to begin using the application As a new user I want to create an account Scenario: Signup with valid email/password combination Given I do not have an account When I signup with email and password Then I should be logged in And my profile details should be filled in 1 scenario (1 undefined) 4 steps (3 undefined, 1 passed) 0m0.136s
  36. 36. rinse and repeat
  37. 37. Feature: Standard Signup In order to begin using the application As a new user I want to create an account Scenario: Signup with valid email/password combination Given I do not have an account When I signup with email and password Then I should be logged in And my profile details should be filled in 1 scenario (1 passed) 4 steps (4 passed) 0m0.138s
  38. 38. Before do # do before each scenario end After do # do after each scenario end AfterStep do # do after each Given/When/Then/And/But step end Before("@tagged") do # do before scenarios tagged with @tagged end
  39. 39. # features/support/time.rb module TimeHelpers def set_zone(zone_name) Time.zone = zone_name end end World(TimeHelpers) # features/step_definitions/user_steps.rb Given /^I am in the "([^"]*)" time zone$/ do |zone| set_zone(zone) end
  40. 40. good stories are hard to write
  41. 41. start with the value proposition
  42. 42. Feature: Name or theme
  43. 43. Feature: Name or theme In order to make, protect, or save money As a stakeholder I want to have some feature
  44. 44. Feature: School account management In order to maximize revenue by offering our product to multiple schools at once As the site owner I want to provide individual accounts to each school and manage them
  45. 45. Feature: School account management In order to maximize revenue by offering Schoolbinder to multiple schools at once As the site owner I want to provide individual accounts to each school and manage them Scenario: List accounts Scenario: Create an account Scenario: Revoke an account Scenario: List admin users for accounts Scenario: Change subdomain for account
  46. 46. Feature: School account management In order to maximize revenue by offering Schoolbinder to multiple schools at once As the site owner I want to provide individual accounts to each school and manage them Scenario: List accounts Then I should see a list of accounts
  47. 47. Feature: School account management In order to maximize revenue by offering Schoolbinder to multiple schools at once As the site owner I want to provide individual accounts to each school and manage them Scenario: List accounts When I go to the accounts page Then I should see a list of accounts
  48. 48. Feature: School account management In order to maximize revenue by offering Schoolbinder to multiple schools at once As the site owner I want to provide individual accounts to each school and manage them Scenario: List accounts Given I am logged in as the site owner When I go to the accounts page Then I should see a list of accounts
  49. 49. descriptive > imperative
  50. 50. intention > implementation
  51. 51. # descriptive When I create a new account for "ms218" # imperative When I follow "New account" And I fill in "Name" with "ms218" And I submit the form
  52. 52. descriptive stories are flexible
  53. 53. strike balance too implicit = vague
  54. 54. avoid conjunctive statements
  55. 55. # conjunctive When I change my name to "Sean" and my password to "foobar" # independent When I change my name to "Sean" And I change my password to "foobar"
  56. 56. strive for single passes
  57. 57. # conflated scenarios, multiple passes Scenario: Bulk comment on short term goals Given I have set all short-term goals for "ELA > Writing > Organization" for class "601" When I follow "Edit" for long-term goal "Organization" And I follow "Comment" for short-term goal "Coherence" Then I should see all students that pertain to this short-term goal And I should see the standard comment box and "Post new comment" button When I type in the comment box And I follow "Post" Then I should see that my comment was posted # single scenario, single pass Scenario: Bulk comment on short term goals Given I have set all short-term goals for "ELA > Writing > Organization" for class "601" When post a comment for short-term goal "Coherence" Then I should see that my comment was posted And all students in class "601" should receive my comment
  58. 58. stay terse cover corner cases
  59. 59. Background: Given an account for subdomain "ms217" And these administrators for subdomain "ms217": | email | name | | joe@ms217.edu | Joe Smith | | jane@ms217.edu | Jane Doe | And this welcome message for subdomain "ms217": """ Welcome back, students! - The principal """
  60. 60. Scenario Outline: Successful authentication with email Given a <type> named "<first name> <last name>" with email <email> and password "<password>" And I am on the login screen When I login with "<email>" and "<password>" Then I should be logged in Examples: | type | email | first name | last name | password | | student | joe@school.edu | Joe | Smith | testing123 | | teacher | jane@school.edu | Jane | Brown | testing456 | | staff | mark@school.edu | Mark | White | testing789 | | admin | paul@school.edu | Paul | Greene | testing098 |
  61. 61. <self:promotion>
  62. 62. </self:promotion>
  63. 63. questions?

×