Your SlideShare is downloading. ×
0
Writing BetterDomain Oriented  Cucumber   Features   Amir Barylko
Better Cucumber FeaturesWho am I?•   Architect•   Developer•   Mentor•   Great cook•   The one who’s entertaining you for ...
Behavior Driven Dev.           Text            Text                   The rSpec Book
Amir Barylko - Better Cucumber FeaturesWhy Projects Fail?• Delivering   late or over budget• Delivering   the wrong thing•...
Amir Barylko - Better Cucumber FeaturesImprove Quality• Unit Testing• Integration Testing• Acceptance Testing
Amir Barylko - Better Cucumber FeaturesBDD• Implementing    an application• by   describing its behavior• from   the persp...
Amir Barylko - Better Cucumber FeaturesOutside In Approach       BDD                TDD
Amir Barylko - Better Cucumber FeaturesTest First• Write   a test before any line of code• Write minimum amount of code to...
Cucumber
Amir Barylko - Better Cucumber FeaturesGherkin DSL•   Business readable DSL•   Flush out requirements•   Documentation•   ...
Amir Barylko - Better Cucumber FeaturesGherkin Keywords• Feature        • Then• Scenario       • And• Given          • But...
Amir Barylko - Better Cucumber FeaturesFeaturesFeature: Listing projects  As a user                           Free        ...
Amir Barylko - Better Cucumber FeaturesScenarioScenario: List all projects  Given Im logged in                            ...
Amir Barylko - Better Cucumber FeaturesRunning Features•   Parse the feature    •   Parse the scenario        •   For each...
Amir Barylko - Better Cucumber FeaturesMatching Step• Matching   regular expression Given I have some projects stored     ...
Amir Barylko - Better Cucumber FeaturesStepGiven /^I have some projects stored$/ do  projects = 10.times { random_valid_pr...
Expressive Scenarios
Amir Barylko - Better Cucumber FeaturesWhat we want?•   Readability•   Ubiquitous Language•   Consistent use of terminolog...
Amir Barylko - Better Cucumber FeaturesImperative styleScenario: Redirect user to originally requested page  Given a User ...
Amir Barylko - Better Cucumber FeaturesWhat’s the problem?•   Who needs the passwords?•   Tightly coupled to page implemen...
Amir Barylko - Better Cucumber FeaturesDeclarative styleScenario: Redirect user to originally requested page  Given I am a...
Amir Barylko - Better Cucumber FeaturesDeclarative vs Imperative• Imperative   is associated to “how” to do it• Declarativ...
Amir Barylko - Better Cucumber FeaturesToo abstract?Scenario: The whole system Given the system exists When   I use it The...
Amir Barylko - Better Cucumber FeaturesBackground steps•   Steps may have some degree of repetition•   Because they start ...
Amir Barylko - Better Cucumber FeaturesSimilar scenariosScenario: Change Password  Given I am logged in  And    I choose t...
Amir Barylko - Better Cucumber FeaturesCreate BackgroundBackground: I want to change my password  Given I am logged in  An...
Amir Barylko - Better Cucumber FeaturesUsing Tables•   Sometimes data is hard to put in a step•   with multiple entriesSce...
Amir Barylko - Better Cucumber FeaturesThat’s boring!•   Express data in tabular formScenario: Listing movies    Given the...
Amir Barylko - Better Cucumber FeaturesOr just a list•   Don’t use the headerScenario: Listing movies    Given these movie...
Amir Barylko - Better Cucumber FeaturesWhy the detail though?•   Do you really need the list?Scenario: Listing movies    G...
Amir Barylko - Better Cucumber FeaturesLeaky Scenarios•   Each scenario leaves the system in a    particular state•   The ...
Amir Barylko - Better Cucumber FeaturesGenerating data•   Use a framework to generate valid data•   FactoryGirl is a very ...
Amir Barylko - Better Cucumber FeaturesTransforms•   Steps can have arguments•   Though regular expression they don’t alwa...
Amir Barylko - Better Cucumber FeaturesSteps with argumentsGiven /^I search for a movie “([^"]*)”$/ do |name|  .... # some...
Amir Barylko - Better Cucumber FeaturesCapture the argumentGiven /^I search for a movie “(#{MOVIE_NAME})”$/ do |name|  ......
Amir Barylko - Better Cucumber FeaturesHelpers•   Helpers are a great tool to encapsulate    common functionality•   Or to...
Amir Barylko - Better Cucumber FeaturesCurrent Instance•   The World is created for each scenario•   Instance variables ha...
Amir Barylko - Better Cucumber FeaturesHelper Classmodule ProjectHelper  def current_project(project = nil)    @current_pr...
Amir Barylko - Better Cucumber FeaturesCustom matchersRSpec::Matchers.define :match_stored_projects do  match do |actual| ...
Amir Barylko - Better Cucumber FeaturesPage Objects•   The steps rely on the HTML implementation•   Searching for elements...
Amir Barylko - Better Cucumber FeaturesWhat can we do?Then /^I should see the complete list of projects$/ do  actual = all...
Amir Barylko - Better Cucumber FeaturesAbstraction!class ProjectListPage    include PageObject•      def projects        a...
Amir Barylko - Better Cucumber FeaturesNicer stepsThen /^I should see the complete list of projects$/ do  projects_page.li...
Amir Barylko - Better Cucumber FeaturesWith a custom matcherThen /^I should see the complete list of projects$/ do  projec...
Summary
Amir Barylko - Better Cucumber FeaturesNext steps•   Focus your scenarios on “what” not “how”•   Read about scenario outli...
Amir Barylko - Better Cucumber FeaturesResources• Email: amir@barylko.com,• Twitter: @abarylko• Blog: http://orthocoders.c...
Amir Barylko - Better Cucumber FeaturesResources II
Upcoming SlideShare
Loading in...5
×

DevTeach12-betterspecs

647

Published on

Presentation done at Devteach/RubyTeach 2012

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
647
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
12
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "DevTeach12-betterspecs"

  1. 1. Writing BetterDomain Oriented Cucumber Features Amir Barylko
  2. 2. Better Cucumber FeaturesWho am I?• Architect• Developer• Mentor• Great cook• The one who’s entertaining you for the next hour!
  3. 3. Behavior Driven Dev. Text Text The rSpec Book
  4. 4. Amir Barylko - Better Cucumber FeaturesWhy Projects Fail?• Delivering late or over budget• Delivering the wrong thing• Unstable in production• Costly to maintain
  5. 5. Amir Barylko - Better Cucumber FeaturesImprove Quality• Unit Testing• Integration Testing• Acceptance Testing
  6. 6. Amir Barylko - Better Cucumber FeaturesBDD• Implementing an application• by describing its behavior• from the perspective of the stakeholder
  7. 7. Amir Barylko - Better Cucumber FeaturesOutside In Approach BDD TDD
  8. 8. Amir Barylko - Better Cucumber FeaturesTest First• Write a test before any line of code• Write minimum amount of code to make the test pass• Refactor code to eliminate “smells”
  9. 9. Cucumber
  10. 10. Amir Barylko - Better Cucumber FeaturesGherkin DSL• Business readable DSL• Flush out requirements• Documentation• Automated testing• Used by Cucumber, SpecFlow, jBehave
  11. 11. Amir Barylko - Better Cucumber FeaturesGherkin Keywords• Feature • Then• Scenario • And• Given • But• When
  12. 12. Amir Barylko - Better Cucumber FeaturesFeaturesFeature: Listing projects As a user Free text! I Want to see the list of projects So I can choose one to see the details Scenario: List all projects (steps here to implement scenario) Scenario: No projects are available (steps here to implement scenario)
  13. 13. Amir Barylko - Better Cucumber FeaturesScenarioScenario: List all projects Given Im logged in Step 1 And I have some projects stored Step 2 When I browse the projects Step 3 Then I should see all of them listed Step 4
  14. 14. Amir Barylko - Better Cucumber FeaturesRunning Features• Parse the feature • Parse the scenario • For each scenario • Find a step implementation • Execute the code
  15. 15. Amir Barylko - Better Cucumber FeaturesMatching Step• Matching regular expression Given I have some projects stored Feature File Given /^I have some projects stored$/ Step Def File
  16. 16. Amir Barylko - Better Cucumber FeaturesStepGiven /^I have some projects stored$/ do projects = 10.times { random_valid_project } fake_response = create_response(projects) FakeWeb.register_uri(....)end Plain Ruby!
  17. 17. Expressive Scenarios
  18. 18. Amir Barylko - Better Cucumber FeaturesWhat we want?• Readability• Ubiquitous Language• Consistent use of terminology• Express natural business intent• Avoid technical aspects
  19. 19. Amir Barylko - Better Cucumber FeaturesImperative styleScenario: Redirect user to originally requested page Given a User "dave" exists with password "secret" 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 "dave" And I fill in "Password" with "secret" And I press "Login"
  20. 20. Amir Barylko - Better Cucumber FeaturesWhat’s the problem?• Who needs the passwords?• Tightly coupled to page implementation• Lacks domain language• Brittle tests• Does not tell a story (boring)
  21. 21. Amir Barylko - Better Cucumber FeaturesDeclarative styleScenario: Redirect user to originally requested page Given I am an authenticated user When I attempt to view restricted content Then I am presented with a login form When I authenticated with valid credentials Then I should be shown the restricted content
  22. 22. Amir Barylko - Better Cucumber FeaturesDeclarative vs Imperative• Imperative is associated to “how” to do it• Declarative is associated to “what” we want• Where’s the boundary?
  23. 23. Amir Barylko - Better Cucumber FeaturesToo abstract?Scenario: The whole system Given the system exists When I use it Then it should work, perfectly
  24. 24. Amir Barylko - Better Cucumber FeaturesBackground steps• Steps may have some degree of repetition• Because they start with the same “state”• So they share the first X steps
  25. 25. Amir Barylko - Better Cucumber FeaturesSimilar scenariosScenario: Change Password Given I am logged in And I choose to change my password When I enter a new password Then my password should be changedScenario: Change Password with same credentials Given I am logged in And I choose to change my password When I enter the same password Then I should see an error message explaining the problem
  26. 26. Amir Barylko - Better Cucumber FeaturesCreate BackgroundBackground: I want to change my password Given I am logged in And I choose to change my passwordScenario: Change Password When I enter a new password Then my password should be changedScenario: Change Password with same credentials When I enter the same password Then I should see an error message explaining the problem
  27. 27. Amir Barylko - Better Cucumber FeaturesUsing Tables• Sometimes data is hard to put in a step• with multiple entriesScenario: Listing movies Given the movie “Blazing saddles” released “7 Feb 1974” And the movie “Young Frankenstein” released “15 Dec 1974” And the movie “The Producers” released “10 Nov 1968”
  28. 28. Amir Barylko - Better Cucumber FeaturesThat’s boring!• Express data in tabular formScenario: Listing movies Given these movies: | title | release | | Blazing saddles | 7 Feb 1974 | | Young Frankenstein | 15 Dec 1974 | | The Producers | 10 Nov 1968 |
  29. 29. Amir Barylko - Better Cucumber FeaturesOr just a list• Don’t use the headerScenario: Listing movies Given these movies: | Blazing saddles | | Young Frankenstein | | The Producers |
  30. 30. Amir Barylko - Better Cucumber FeaturesWhy the detail though?• Do you really need the list?Scenario: Listing movies Given I have some movies stored When I browse the list Then I should see the complete collection
  31. 31. Amir Barylko - Better Cucumber FeaturesLeaky Scenarios• Each scenario leaves the system in a particular state• The state has to be cleaned up for the next scenario• Otherwise it will “leak” into it• One scenario should not depend on another
  32. 32. Amir Barylko - Better Cucumber FeaturesGenerating data• Use a framework to generate valid data• FactoryGirl is a very good option • FactoryGirl.create(:customer) • FactoryGirl.create(:invalid_bank_accout)• Faker will help you to generate fake data
  33. 33. Amir Barylko - Better Cucumber FeaturesTransforms• Steps can have arguments• Though regular expression they don’t always show intent• And also we may need to “reuse” them
  34. 34. Amir Barylko - Better Cucumber FeaturesSteps with argumentsGiven /^I search for a movie “([^"]*)”$/ do |name| .... # some code hereendGiven /^I have a movie called “([^"]*)”$/ do |name| .... # some code hereend
  35. 35. Amir Barylko - Better Cucumber FeaturesCapture the argumentGiven /^I search for a movie “(#{MOVIE_NAME})”$/ do |name| .... # some code hereendMOVIE_NAME = Transform /^([^"]+)$/ do | movie_name | movie_name.downcaseend
  36. 36. Amir Barylko - Better Cucumber FeaturesHelpers• Helpers are a great tool to encapsulate common functionality• Or to help describe better our intention• and to avoid looking at ugly code
  37. 37. Amir Barylko - Better Cucumber FeaturesCurrent Instance• The World is created for each scenario• Instance variables have to be set• Instead we can use a helper method• to store/create the resource
  38. 38. Amir Barylko - Better Cucumber FeaturesHelper Classmodule ProjectHelper def current_project(project = nil) @current_project ||= project end def project_list_page @project_list_page ||= ProjectListPage.new endendWorld(ProjectHelper)
  39. 39. Amir Barylko - Better Cucumber FeaturesCustom matchersRSpec::Matchers.define :match_stored_projects do match do |actual| actual == Project.all.map { ... } end failure_message_for_should do |actual| "The projects in the page should match...n" + "The page contains #{actual} n" + "But the storage contains #{@expected}" endend
  40. 40. Amir Barylko - Better Cucumber FeaturesPage Objects• The steps rely on the HTML implementation• Searching for elements can be repetitive• or ugly• and not always show intention
  41. 41. Amir Barylko - Better Cucumber FeaturesWhat can we do?Then /^I should see the complete list of projects$/ do actual = all(:css, "#projects tbody tr")• .map { |tr| tr.all("td").map(&:text) } .map { |cells| ... } expected = Project.all.map { |p| ... } actual.should == expectedend
  42. 42. Amir Barylko - Better Cucumber FeaturesAbstraction!class ProjectListPage include PageObject• def projects all(:css, "#projects tr"). drop(1). #drop the header map { |r| r.all(:css, td).map(&:text) }. map { |r| Project.new(...) } endend
  43. 43. Amir Barylko - Better Cucumber FeaturesNicer stepsThen /^I should see the complete list of projects$/ do projects_page.list.should == stored_projects•end Page Object Helper
  44. 44. Amir Barylko - Better Cucumber FeaturesWith a custom matcherThen /^I should see the complete list of projects$/ do projects_page.should list_stored_projects•end Custom Matcher
  45. 45. Summary
  46. 46. Amir Barylko - Better Cucumber FeaturesNext steps• Focus your scenarios on “what” not “how”• Read about scenario outlines• Follow “the Cucumber book” practices• Learn more about page objects pattern• Start with a simple project
  47. 47. Amir Barylko - Better Cucumber FeaturesResources• Email: amir@barylko.com,• Twitter: @abarylko• Blog: http://orthocoders.com• Website: http://maventhought.com
  48. 48. Amir Barylko - Better Cucumber FeaturesResources II
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×