DRY up your Cucumber Steps

Update (13th Jume 2012): This is an old, old post that still gets a lot of hits. I don’t recommend this practice anymore. Instead, I recommend composing Ruby methods that carry out these actions. For more details, please see The Cucumber Book.

A while back, I asked the Cucumber team for the ability to call in the steps of one scenario from another.

The canonical example of this is the ‘log in’ scenario:

Scenario: User logs in
  Given there is a User whose username is "matt"
  And I follow "log in"
  And I enter "matt" in "username"
  And I enter the User's password in "password"
  And I press "Log In"
  Then I should be logged in
  And I should see the text "Hello matt"

Phew. Now obviously I don’t want all this noise in the scenario every time I specify behaviour that requires a logged in user. I want to write something like this:

Scenario: User views their dashboard
  Given I am logged in
  And I follow the "dashboard" link
  Then I should see "This is your dashboard"

Thanks to the fabulous creativity of the Cucumber community, this is now possible. It’s also highly recommended, as it’s a great way to help you keep your step files tidy and DRY of excess duplication.

Given /I am logged in/ do
  steps %{
    Given there is a User
    When I follow "log in"
    And I enter "#{User.first.username}" in "username"
    And I enter "#{User.first.password}" in "password"
    And I press "Log In"
  }
end

I’m doing this more and more now – writing simple ‘building block’ steps and assembling them to make steps that read nicely and make sense to the stakeholders.

Published by Matt

I write software, and love learning how to do it even better.

Join the Conversation

13 Comments

  1. i know this thread is old but what about scenarios that require reuse of a set of data. My example is a set of flights. I have several scenarios for delaying, canceling, or other scheduling based actions that all need a set of flights over time that are affected by the actions. I would like to define this set in one place and reuse them in the different scenarios probably using a Background: type given scenario. Is there a way to do this or a better suggestion for handling this?

  2. Hi Wes,

    It definitely sounds like Background would fit well for you – you can set up the data in the background then carry out different actions on it in different scenarios. The advantage of doing this is your tests are very clear about the data being set up. The disadvantage is that you can’t vary that data at all in the different scenarios. Spelling out the data to use can also be a bit noisy – sometimes the specific data you use doesn’t matter – you just want the general sense of the state of the system.

    See this excellent post by Ben Mabey on that subject.

  3. Thanks a lot, very useful.
    A must have if your serious about testing
    I was trying to find your article using “cucumber nested given” on google which didn’t work.
    So I thought i’d add the keywords in the comment.

  4. Thanks for the post, I was in the same place of reusing steps for testing user authentication with authlogic.

  5. Yes reusing Gherkin steps in the step definitions was a huge progress. However I really miss the matching feature in Gherkin space. RSpec has its Shared Examples feature and I have always wondered why the Cucumber team never wanted to augment Gherkin to allow a better behaviour factoring.

    Isolating the stakeholders from the programming language is one of the main justification of Cucumber so why are we forced to enter the step definition space to get a nice feature like nested specifications ?

    An example is here: https://gist.github.com/1084580

  6. I agree Arnaud, it would be better if these mappings were surfaced in Gherkin. However it’s not easy to do technically, so it’s hasn’t been implemented yet. I hope it will happen eventually, but we might have to wait for Cucumber 2.0!

  7. Thanks for the info!

    Just a quick update: using ‘given’ and ‘when’ as part of a step definition is now deprecated, and the cucumber team wants you to use ‘step’ instead (according to my console output).

Leave a comment

Your email address will not be published. Required fields are marked *