Practical Cucumber: Scenario-specific steps

This post is part of our Practical Cucumber series.

Here is an example of how NOT to write cucumber scenarios:

Given a product named "Some Product"
When I add "Some Product" to my favorites
Then I should see "Some Product" in my favorites

What’s wrong with this? Not only does it communicate nothing about how this feature works to the end user, it defines very specific steps that will likely only be used in this scenario.

Cucumber steps are meant to be reused. If you are defining steps that are only used once, you’re probably doing it wrong. You should eventually get to the point in your app where you rarely have to implement a step in order to write a new scenario.

Here is an example of the above step rewritten. This time it requires no custom steps:

Given the following product exists:
  | Name         |
  | Some Product |
When I go to the home page
And I follow "Some Product"
And I press "Add to Favorites"
And I follow "Favorites"
Then I should see "Some Product"

The first step comes from factory_girl (which we’ll post more about), and the rest are defined in the web_steps.rb.

While this version is longer and more verbose, it is infinitely better. It clearly communicates how the enduser will experience this feature and required no code, allowing you to focus your programming prowess on the implementation.

This post is part of our Practical Cucumber series.

brandon@opensoul.org

Comments

  1. September 09, 2010 at 18:03 PM

    This is great advice, and I need to follow it more.

    One problem I frequently run into, though, is trying to keep view implementation details out of my features and into my steps. I frequently have a problem where I define some things about the view that a designer then changes. These aren’t important changes either. For instance, what if the designer doesn’t like “Add to Favorites” and changes it to “Favorite”? Then the build breaks because of a wording change, but the feature should be a description of functionality, not a description of the view implementation.

    I believe I read a post from Bryan Helmkamp that recommended writing features more like your first example. It pushes view implementation details into the steps and keeps the features as descriptions of the business requirements, not of the interface. The test may still break if wording changes (unless you’re smarter and press buttons or click links by id instead of label) but they will break in the steps instead of the features the stakeholders see.

    This strategy does make you write a lot of steps, but I try to keep these organized and continue to refactor them as needed.

    Can you comment on how to reconcile these different strategies?

  2. September 09, 2010 at 18:52 PM

    Tony Hillerson: Thanks for sharing your struggles.  We have definitely felt your pain.

    However, in many cases, the text on the page is actually significant.  As developers, we tend to diminish the importance of design and words, but to many clients, the form is equally as important as the function. It is all part of the acceptance criteria. The overhead of having to change the text every once in a while is insignificant compared to the overhead of writing custom steps for every scenario, just in case the text ever changes.

    If it is something that changes frequently, and the cost of maintenance becomes too high, then abstract it in a way that doesn’t cause you to incur technical debt with every new scenario. The way that the built in web_steps.rb handles paths is a perfect example.  There are several steps around navigating to the correct page, and they delegate to one method to determine the actual route.

    We will be posting soon on a way we’ve used this pattern to scope to elements on the page.

  3. hey.rob.saunders@gmail.com
    Rawb
    November 01, 2010 at 11:20 AM

    Thank you infinitely for this.
    This single post was one of those ‘click’ moments for me, where cucumber finally started to make so much more sense.

  4. briskm23@gmail.com
    dev
    May 18, 2011 at 7:28 AM

    if you are going to test a table, at that time how ll you write scenarios?

    Can u pls explain me with example

  5. June 05, 2011 at 15:42 PM

    Another approach to keep your cucumber steps safe regarding text changes is to use the translation framework throughout your application to unify the access to any text passages. Then in your step definitions you also use the translation key to let capybara always click the correct button etc.
    Cucumber scenarios should not break because of a changing the text.

  6. June 05, 2011 at 16:04 PM

    @Dominik That’s a fantastic idea! I’ll be sure to do that moving forward. You’re absolutely right that Cucumber shouldn’t depend on specific text content. It makes for brittle tests and I’ve run into that very problem far too often. Thanks!

  7. michiru@gmail.com
    Lauren
    November 01, 2011 at 6:52 AM

    Yeah this is exactly what the cucumber developer says not to do. I would not do this.

    Here is an an article he links to as an example of how to write cucumber tests http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html

  8. November 01, 2011 at 12:43 PM

    Lauren,

    Yeah, we’re in disagreement on that point. We actually find that using web steps with good markup make features more maintainable. We’ll be blogging more about how we think to do it well.

  9. melezhik@gmail.com
    Alexey
    April 02, 2012 at 13:26 PM

    I disagree with approach above,  the first feature is quite abstract and is not coupled with implementation (link names, button captions), and “improved” feature is coupled with this kind of knowledge, just one question: what happen is someone rename “Favorite” link to say “My Selected Products” or rename button “Add to Favorites” to “Add to my favorites”, whatever … You’d have to look all over the features code to fix this issue, while this kind details should encapsulated in domain classes not in features files ..

    Also reusing a steps ( actually reusing a stepdefs ) a really bad idea in cucumber, although it supports for it, you’d better think about reusing on domain level but not on features/stepdefs levels in cucumber stack

    The main rule for features should be to detailed and be coupled with concrete implementation details 

  10. melezhik@gmail.com
    Alexey
    April 02, 2012 at 13:31 PM

    Sorry for typo, In last phrase I meant “The main rule for features - they should NOT …”

  11. April 02, 2012 at 14:56 PM

    Alexey: For stuff that changes often, take a look at the selectors file in what is now the sadly-named cucumber-rails-training-wheels It is an approach I like a lot. 

    Why I like using text for much of our tests is that it is what the user sees. I want to be testing their flow, not a highly abstracted version. 

    As far as step reuse, I think that is one of the best features of Cucumber. In our experience, features are more stable when you don’t have tons of custom steps. Reuse is key.

    Thanks for you thoughts though. I know we’ll never be on the same page with everyone.

  12. antonot20052012@gmail.com
    Habzossekes
    August 05, 2012 at 18:02 PM

    http://s012.radikal.ru/i320/1112/5b/5919d02f5246.jpg</img>
    http://s47.radikal.ru/i118/1112/cd/2e0462ac92b8.jpg</img></a>

    Tegs: декоративная штукатурка сходненская декоративная штукатурка малярные работы дизайн стен декоративная штукатурка.

    декоративная штукатурка видео уроки
    воск для декоративной штукатурки
    декоративная штукатурка шуба

  13. phil@electricvisions.com
    PhilT
    March 20, 2013 at 13:48 PM

    This is not the only way. See:

    http://aslakhellesoy.com/post/11055981222/the-training-wheels-came-off
    http://robots.thoughtbot.com/post/25650434584/writing-better-cucumber-scenarios-or-why-were
    http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html