In this recipe, will cover various kinds of tips for writing good, maintainable, and DRY Cucumber steps.
We will reuse the Rails application cucumber_bdd_how_to
that we've created in the Writing your first Hello World feature (Simple) recipe, so please cd
into that directory to get prepared.
In the following sections, a number of useful step tips will be introduced and covered exhaustively.
When the user has 1 gift ... When the user has 5 gifts ...
When /^the user has (d+) gifts?$/ do |num| p num.to_i end
?
(question mark) appended to gifts
; it means match zero or more of the proceeding character, and so the step definition will match both gift
and gifts
.When there is 1 person in the meeting room When there are 8 people in the meeting room
When /^there (?:is|are) (d+) (?:person|people) in the meeting room$/ do |num| p num.to_i end
?:
before a normal group, the step will try to match one occurrence of the given word and will not pass the matched value into arguments. Non-capturing groups ensure Gherkin's good readability when dealing with singulars and plurals, and in a DRY manner since one generic step matches various kinds of styles.Transform /^(-?d+)$/ do |num| num.to_i end
Given this Qatar billionaire has 39 billion And his wealth consists of the following major parts | Domain | Worth | | Oil | 21 | | Real Estate | 8 | | Financial | 6 | | Cargo | 4 |
Transform /^table:domain,worth/ do |table| table.map_headers! { |header| header.downcase.to_sym } table.map_column!(:domain) { |domain| Domain.parse(domain) } table.map_column!(:worth) { |worth| "$#{worth}" } table end
features/support
directory, for example creating a current_user
method and putting it under features/support/current_user.rb
:def current_user # Code to mock a current user object end
World
interface to mix in customized modules, for example, we can define an add_headers
method:module CapybaraHeadersHelper def add_headers(headers) headers.each do |name, value| page.driver.browser.header(name, value) end end end World(CapybaraHeadersHelper)
add_headers
method from the CapybaraHeadersHelper
module to add a customized HTTP header when requesting web pages during a test.Methods can be reused, and so can steps! This is a widely used tip for writing good and DRY Cucumber steps, known as compound steps.
Feature: Login with 3rd party account As a website user I can login with 3rd party account So that I don't have to register a new account Scenario: Login with Facebook account Given user landed at login page And he choose login with FacebookThen he should see the Facebook authorization window Scenario: Login with Google account Given user landed at login page And he choose login with Google Then he should see the Google authorization window Scenario: Login with OpenID account Given user landed at login page And he choose login with OpenID Then he should see the OpenID login window
user choose login with **
can be implemented using the DRY principle as follows:Given /^he choose login with (.*)$/ do |account_provider| step %{user clicks on the #{account_provider} logo} step %{login with #{account_provider}} end Given /^user clicks on the (.*) logo$/ do |account_provider| # DOM operation to trigger clicking on the related logo end Given /^login with (.*)$/ do |account_provider| # Implement OAuth login per given 3rd party account end
^
and ends with $
. It looks as follows:Given /^user landed at login page$/ do end
^
and $
are called "anchors". The preceding step uses ^
and $
to match the string user landed at login page
exactly; then we could probably employ "unanchored steps" as follows:Then /^wait (d+) seconds?/ do |seconds| sleep(seconds.to_i) end
?
, to match the flexible pluralization instead of $
, which means all steps containing "wait for x second(s)" will be matched by the preceding step definition, for example:When I wait 5 seconds after the certificate has been downloaded When I wait 4 seconds until the loading animation finished
Other than the preceding technical tips, the last one, and also the most important tip, is to keep your steps organized!
All the preceding tips are targeted at writing maintainable and DRY Cucumber steps. The last tip is to keep Cucumber steps organized, which is kind of a "soft" skill, even though it might be the most important! Categorizing features and step definition files, using tags or hooks, using Rake tasks to encapsulate common running features, and so on; these "rules" are unobtrusive but really important to keep the Cucumber tests maintainable and make daily BDD development life easier.
3.12.162.37