(My) Cucumber best practices and tips

After (My) RSpec best practices and tips, I’m happy to share my Cucumber best practices and tips!

This article will help you organize, clarify and reduce the size of your cucumber scenarios.

1. Organize your garden

Keep your feature files organized by grouping them by business object, then action and context if any. I put all the feature files in the same directory. For instance:

bank_account_add.feature
bank_account_delete.feature
user_signup.feature
user_signup_when_invited.feature
user_login.feature

The steps specific to the application should be organized by business object as well (bank_account_steps.rb, user_steps.rb…). Keep the file organized grouping the steps by Given / When / Then.

Do not overload the files generated by Cucumber like step_definitions/web_steps.rb and support/env.rb with your own steps, helpers or setup code. These files are likely to get overwritten when you update Cucumber so store your stuff in your own files.

2. Custom steps make your scenario DRY and accessible

Scenarios should have the same lifecyle as your code: Red, Green, Refactor to make them DRY and easy to read.

Group multiple steps together. For instance:

  Given I follow "Send money"
  When I fill in "Email" with "mukmuk@example.com"
  And I fill in "Amount" with "10"
  And I select "Bank account" from "Source"
  And I press "Send"
  Then I should see "You've sent $10 to mukmuk@example.com"

… could be refactored to:

  Given I send "$10" to "mukmuk@example.com" from my "Bank account"

This step definition is the following:

  Given %{I send "$amount" to "$email" from my "$source"} do |amount, email, source|
    Given %{I follow "Send money"}
    When %{I fill in "Email" with "#{email}"}
    And %{I fill in "Amount" with "#{amount.delete('$')}"}
    And %{I select "#{source}" from "Source"}
    And %{I press "Send"}
    Then %{I should see "You've sent $#{amount} to #{email}"}
  end

This step can then be easily reused in other scenario keeping your features DRY. It also decouples the scenario from the UI so that you won’t have to change dozens of feature files when the UX guru changes translations or user flows.

3. Background: setup the DRY way

Make the feature focus on one business object/action/context and the background will get longer than the scenarios.

  Feature: A user can cancel a transaction unless it's claimed by the recipient

    Background:
      Given I am logged in
      And I send "$10" to "mukmuk@example.com" from my "Bank account"

    Scenario: I can cancel as long as the payment is not claimed
      When I cancel my latest transaction
      Then I should see a cancellation confirmation

    Scenario: I can't cancel once the payment is claimed
      Given "Mukmuk" claimed the latest transaction
      Then I can't cancel my latest transaction

4. Scenario outlines: scenario with variables!

A scenario outline contains variables allowing you to test multiple context using a truth table. For instance I use them to make sure that validation errors are displayed properly:

  Scenario Outline: Add invalid bank account displays inline errors
    Given I follow "Add Bank Account"
    When I fill in "<field>" with "<value>"
    And I press "Add Bank Account"
    And I should see the inline error "<error>" for "<field>"

    Examples:
      | field   | value         | error                    |  
      | Account |               | Can't be blank           |  
      | Account | Sixty five    | Should be 1 to 12 digits |  
      | Account | 1234567890123 | Should be 1 to 12 digits |  

5. Multi-line step arguments: give your step a table for lunch!

A step can take a multi-line table as an argument. This is a great way to load up a bunch of data or to test the rendering of lists and tables. For instance:

  Given I sent "$25" to "mukmuk@example.com" from my "Bank account"
  Then I should see the following transaction history:
    | create     | complete    |
    | deposit    | in_progress |
    | transfer   | pending     |
    | withdrawal | pending     |

The step definition looks like the following:

  Then "I should see the following transaction history:" do |table|
    table.raw.each do |event, state|
      page.should have_css("tr.#{event}.#{state}")
    end
  end

I hope that these tips will help you growing healthy cucumber features!

Want more? Check out the Cucumber wiki, 15 Expert Tips for Using Cucumber by Dave Astels, You’re Cuking It Wrong by Elabs and You’re almost cuking it… by Antony Marcano. You could also like (My) RSpec best practices and tips. :)

Happy BDD!

Thanks to Jean-Michel Garnier for reviewing this article.

Post to Twitter

. Bookmark the permalink. Both comments and trackbacks are currently closed.
  • http://www.fakingfantastic.com Frank Lakatos

    Thanks for this article. It was extremely helpful, as I had no idea step definition could be made up of other step definitions. I’ve got a lot of refactoring to do.

  • http://wwww.21croissants.com Jean-Michel

    If there are more than 15 features, it’s hard to read (I am lost when I see a list with more than 7 items). We use sub directories which we intend to map with domains of our application ( hard work and long discussions to decide how to group!). Each sub directory has a step_definitions folder and our cucumber.yml has this little erb in order to load them:

    default: –format progress features –strict –tags ~@wip –no-source –tags ~@draft -r features/support/env.rb -r features/step_definitions

    • http://wwww.21croissants.com Jean-Michel

      wordpress ate my code, this should look better:

      step_definitions = Dir.glob('features/**/step_definitions/*.rb').map { |file| "-r #{file}" }.join(" ")

      default: --format progress features --strict --tags ~@wip --no-source --tags ~@draft -r features/support/env.rb -r features/step_definitions

  • http://www.rubyfleebie.com Frank

    Yes it definitely helps Philippe! Thanks for these precious tips

  • Pingback: The elements of (cucumber) style | Testing with Vision

  • Pingback: (My) RSpec best practices and tips | EggsOnBread

  • Pingback: Useful BDD/Cucumber/Gherkin resources « Twilight Time

  • Pingback: The elements of (cucumber) style | WatirMelon

  • Bikash

    Hi,

    I am new to cucumber.I am facing the problem while acessing the features .it is showing that StepsDefNotFoundException.how can i solve this problem.can any one please help me regarding this.

    Bikash

  • John

    Bikash,

    I am new to this too, but I think the reason is that your step def file is not found. Make sure that your “step_definition” directory is under the features folder.

    HTH.

  • Hi, my name is Philippe Creux.

    This blog is about Agile project management, Ruby programming and other cool things. I haven't published anything here since 2011. Find the latest and greatest on pcreux.com!