Reuse Cucumber steps Reuse Cucumber steps ruby ruby

Reuse Cucumber steps


Note that the method for calling steps within steps has changed in recent versions of cucumber, which you'll see if you get an error like "WARNING: Using 'Given/When/Then' in step definitions is deprecated, use 'step' to call other steps instead:/path/to/step_definitions/foo_steps.rb:631:in `block in '". See the cucumber wiki for details.

The gist of the change is that you should now use the step or steps methods.

When /^I make all my stuff shiny$/  step "I polish my first thing"endWhen /^I make all my stuff shiny$/  steps %Q{    When I polish my first thing    When I shine my second thing  }end


UPDATE: The method described below has been deprecated. The recommended way to call a step from within another step now looks like this:

Given /^I login successfully$/    step "I login with valid credentials" end 

Old, deprecated method (for reference):

You can call steps from other steps like this:

Given /^I login successfully$/  Given "I login with valid credentials"  Then "I should be logged in"end

If all of the scenarios within a feature require this (or other steps), you can also add a Background to each features, with the common steps, like so:

Background:  Given I log in with valid credentialsScenario: Change my password  Given I am on the account page


Calling steps from step definitions is a bad practice and has some disadvantages:

  1. If scenario will fail and there are nested step invocations, you will get only the last invoked step definition in the stack trace. It may be hard to find from which place that last stepdef was called
  2. Call to stepdef is sometimes harder to find and read than ruby method
  3. Ruby methods give you more power than calling steps from step defs

Aslak Hellesøy recommends to extract popular actions to World instead of reusing steps. It isolates those actions in one place, makes this code easier to find. You can extract code to usual Ruby classes or modules as well.

#/support/world_extensions.rbmodule KnowsUser  def login    visit('/login')    fill_in('User name', with: user.name)    fill_in('Password', with: user.password)    click_button('Log in')  end  def user    @user ||= User.create!(:name => 'Aslak', :password => 'xyz')  endendWorld(KnowsUser)#/step_definitions/authentication_steps.rbWhen /^I login$/ do  loginendGiven /^a logged in user$/ do  loginend

Here is a useful discussion on the subject in Cucumber mailing list - link