Grouping steps or concatenating scenarios in Gherkin

2.9k views Asked by At

I'm defining a feature to be used in a BDD workflow with tools such as Behat or Cucumber, using the Gherkin language. This is the feature definition so far:

Feature: Save Resource
    In order to keep interesting resources that I want to view later
    As a user
    I need to be able to save new resources

    Scenario: Saving a new resource
        Given "http://google.com" is a valid link
        When I insert "http://google.com" as the new resource link
        And I insert "Google Search Engine" as the new resource title
        Then I should see a confirmation message with the inserted link and title
        When I accept
        Then I should have 1 additional resource with the inserted link and title

    Scenario: Aborting saving a new resource
        Given "http://google.com" is a valid link
        When I insert "http://google.com" as the new resource link
        And I insert anything as the new resource title
        Then I should see a confirmation message with the inserted link and title
        When I abort
        Then I should have the same number of resources as before

    Scenario: Saving a resource with invalid link
        Given "http://invalid.link" is an invalid link
        When I insert "http://invalid.link" as the new resource link
        And I insert anything as the new resource title
        Then I should see a confirmation message with the inserted link and title
        When I accept
        Then I should see an error message telling me that the inserted link is invalid

    Scenario: Saving a resource with already saved link
        Given "http://google.com" is an already saved link
        When I insert "http://google.com" as the new resource link
        And I insert anything as the new resource title
        Then I should see a confirmation message with the inserted link and title
        When I accept
        Then I should see an error message telling me that the inserted link already exists

As you can see, there's a lot of boilerplate repeated in several scenarios. I know I could define a Background with a list of steps to be executed before all scenarios, where I could put all the steps up to the confirmation message, but if I did that, I wouldn't be able to distinguish among different links and titles that the user might have inserted.

Is it possible to define a background that is used only for certain, and not all, scenarios? Or maybe to concatenate two scenarios, for example requiring that a certain scenario (that I can reuse) is run before another? Or should I simply keep repeating the boilerplate?

2

There are 2 answers

2
diabolist On BEST ANSWER

Following on from Thomas' answer

Your scenarios are complicated and repetitive because each time they are describing 'how' the user interacts with the application. 'How' has no place in scenarios because

  1. The details of how you do things are likely to change as you learn more about what you are doing. You don't want to have to change your scenarios every time you change a detail of how you do something

  2. Putting how in you scenarios makes them boring, repetitive, difficult to read and expensive to implement.

  3. Putting how is your scenarios is generally a way of avoiding doing the real work that scenarios are here for, which is to find out 'why' your are doing something and define elegantly and succinclty 'what' you are trying to achieve.

n.b. there are lots of other reasons

Lets look at how simple your scenarios become when you do this extra bit of work

##Old

Scenario: Saving a new resource
    Given "http://google.com" is a valid link
    When I insert "http://google.com" as the new resource link
    And I insert "Google Search Engine" as the new resource title
    Then I should see a confirmation message with the inserted link and title
    When I accept
    Then I should have 1 additional resource with the inserted link and title

##New

Scenario: Bookmarking
  When I save a bookmark
  Then my bookmark should be saved

##Old

Scenario: Saving a resource with invalid link
  Given "http://invalid.link" is an invalid link
  When I insert "http://invalid.link" as the new resource link
  And I insert anything as the new resource title
  Then I should see a confirmation message with the inserted link and title
  When I accept
  Then I should see an error message telling me that the inserted link is invalid

##New

Scenario: Bookmark with invalid link
  When I bookmark with an invalid link
  Then I should see an invalid link error

etc.

Note how the new scenarios illustrate so clearly just how little you are doing in terms of adding business value!!

As for your question about backgrounds, if you need two different backgrounds you need two different .feature files. This is a good thing!!

2
Thomas Sundberg On

I would consider thinking about what your scenarios are supposed to do. Currently I see scripts that talks about how stuff is done. Almost nothing about what should be done.

Navigation details isn’t really useful for understanding what the system is supposed to do. This is a well known beginners mistake as described in [1] and transcribed in [2].

What you want to do is to push the UI details down the stack. Navigation details lives better in helper methods/classes used by the steps you implement. A page object is one way of hiding navigation from the Scenarios.

Some of your duplication will disappear when you get rid of the navigation details. The remaining duplication might be acceptable for readability reasons.

Remember that understanding the scenarios are much more important than a bit of duplication.

[1] https://cucumber.io/blog/2016/05/09/cucumber-antipatterns

[2] http://www.thinkcode.se/blog/2016/06/22/cucumber-antipatterns