DevTeach12-betterspecs

  • 588 views
Uploaded on

Presentation done at Devteach/RubyTeach 2012

Presentation done at Devteach/RubyTeach 2012

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
588
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
11
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Writing BetterDomain Oriented Cucumber Features Amir Barylko
  • 2. Better Cucumber FeaturesWho am I?• Architect• Developer• Mentor• Great cook• The one who’s entertaining you for the next hour!
  • 3. Behavior Driven Dev. Text Text The rSpec Book
  • 4. Amir Barylko - Better Cucumber FeaturesWhy Projects Fail?• Delivering late or over budget• Delivering the wrong thing• Unstable in production• Costly to maintain
  • 5. Amir Barylko - Better Cucumber FeaturesImprove Quality• Unit Testing• Integration Testing• Acceptance Testing
  • 6. Amir Barylko - Better Cucumber FeaturesBDD• Implementing an application• by describing its behavior• from the perspective of the stakeholder
  • 7. Amir Barylko - Better Cucumber FeaturesOutside In Approach BDD TDD
  • 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. Cucumber
  • 10. Amir Barylko - Better Cucumber FeaturesGherkin DSL• Business readable DSL• Flush out requirements• Documentation• Automated testing• Used by Cucumber, SpecFlow, jBehave
  • 11. Amir Barylko - Better Cucumber FeaturesGherkin Keywords• Feature • Then• Scenario • And• Given • But• When
  • 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. 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. Amir Barylko - Better Cucumber FeaturesRunning Features• Parse the feature • Parse the scenario • For each scenario • Find a step implementation • Execute the code
  • 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. 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. Expressive Scenarios
  • 18. Amir Barylko - Better Cucumber FeaturesWhat we want?• Readability• Ubiquitous Language• Consistent use of terminology• Express natural business intent• Avoid technical aspects
  • 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. 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. 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. 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. Amir Barylko - Better Cucumber FeaturesToo abstract?Scenario: The whole system Given the system exists When I use it Then it should work, perfectly
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Summary
  • 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. Amir Barylko - Better Cucumber FeaturesResources• Email: amir@barylko.com,• Twitter: @abarylko• Blog: http://orthocoders.com• Website: http://maventhought.com
  • 48. Amir Barylko - Better Cucumber FeaturesResources II