Putting Cucumber to Use Titus Fortner HomeAway 5 June 2013 Answers • What exactly is a tool like Cucumber? • Is it something I should use? • What does it look like in practice? • Why did I go out of my way to spend an hour listening to this? It isn’t Magic (Your boss will not all of a sudden be able to write all of your automated tests) Just an Abstraction Layer • Given – Do all of the setting up • When – Take the action under test • Then – Verify results Match the natural language strings with regex With a line of code that you want to run The line of code can be anything you want; it doesn’t have to be for a functional test For Instance Current Code user = owner_multiple_properties get_page(login).login(user) Cucumber feature Given I am logged in as an owner with multiple properties Cucumber step Given /^I am logged in as an owner(?: with )?(multiple properties|a single property)?/ do |which_owner| user = create_owner(which_owner) get_page(login).login(user) Gherkin Abstraction Tools Cucumber uses Ruby with RSpec matchers Options are available in all languages Cucumber, Lettuce, Robot Framework, JBehave Cucumber != BDD / ATDD These tools are often called BDD or ATDD tools – Behavior Driven Development – Acceptance Test Driven Development (I hate that) Natural language abstraction is useful for many other things… Regression Tests, Smoke Tests, “Living Documentation,” etc Use vs Don’t Use • Cucumber is useful – Interface to interact with non-developers • Business? Management? Manual testers? – Distinguish Page Object unit tests (You are writing unit tests for your page objects, right?) from functional tests – Helps focus tests – more on this later… • Cucumber is not useful – Small set of tests – Too much overhead – Only developers will look at the tests The Problem at HomeAway • HomeAway site and features are complicated – Dozens of services – Dozens of brands with one-off features – Constantly adding new features • My Project is the Owner Dashboard • Slowly rolling it out by brand – 5 when I started – 8 now • All the manual testers were testing the entire site; One day for each brand. (That doesn’t scale) Our Approach • Updated project to Webdriver (because) • Hundreds of Test Cases, many written in cucumber format already by business analysts • Re-wrote these with an automation mindset – Build a vocabulary – Use conventions – Move from manual thought process to automated (One action per test) My conventions Given I am logging to Test Case TC37300 And I am logged in as an owner with one property And I am viewing recent activity for an active property listing When I follow View Calendar link Then I should see the current year calendar displayed Spot the Issues • • • • • • • • • • • Given I am an HAO User viewing the login page And I am able to log in When I type “mike” in the user name field And I type “test” in the password field And I click the submit button Then I should see a welcome popup When I cancel welcome popup Then I should see my property information And I should see my user name And The header should say “This is your Property!” And I should see my reviews summary links Imperative vs Declarative What does the consumers of your test care about? -- Mike’s password? -- How we welcome a user? -- The content on the page? -- The exact text of the header? These are the most brittle kinds of tests If this is in your Continuous Integration and your build fails as a result of one of these, are you going to roll it back and fix it? Insist on a high bar for what gets automation Scenario: Log in • • • • • Given I am an Owner And I am viewing the Login Page When I log in with good credentials Then I should be logged in And I should see a welcome message Scenario: Cancel the welcome message • • • • Given I am an Owner And I have logged in When I cancel the welcome message Then I should see the Home Page Steps Issues Given /^I am an? (.*)user (.*) the (.*) (modal|page)$/ do |a,b,c| Matches things like: “I am an awesome user automating the nifty modal that does amazing things” Scenario: Form Submission Given I am logged in as an owner with multiple properties And I am viewing <item_type> list page When I submit <item_type> Then I should see a success message Examples: |item_type| |a reservation| |an inquiry| |a review| Cucumber Steps Given /^I am logged in as an owner(?: with )?(multiple properties|a single property)?/ do |which_owner| user = which_owner.tr(‘ ‘,’_’) get_page(login).login(user) Given /^I am viewing an? (reservation|inquiry|review) list page$/ do |page_type| @action_page = “#{page_type} list” get_page(@action_page) /^When I submit an? (reservation|inquiry|review)$/ do |submit_type| @result_page = @action_page.send(“submit_#{submit_type}”) /^Then I should see an? (success|error) message$/ do |message_type| @result_page.send(“is_#{message_type}_displayed?”).should be_true Considerations • Don’t nest steps! – Abstract in your PageObjects – It is ok to duplicate the PageObject call, the implementation of the PageObject method can change, which object and the method name “shouldn’t” • Be careful with complicated Regex – Just because you can make it work, doesn’t mean you should • Adapt methods to your test language, not the other way around Cuke Approach Improves Testing • Helps enforce the idea that the test language should never change unless the business logic changes • Feature language informs the method names more understandable • Matching vocabulary between page objects • Breaks the focus into concrete chunks (easier to muddle things in Rspec/xUnit type tests • Each chunk is ideally one line to let the Page Object do all the work • Really helps distingush the ‘What’ from the ‘How’