Joseph Wilk

Joseph Wilk

Things with code, creativity and computation.

Cucumber Waves Goodbye to GivenScenario

Cucumber as of version 0.2 has removed the GivenScenario feature. GivenScenario was introduced in the original story runner to allow calling a scenario from another within the same feature.

Scenario: setup
  Given ...

 Scenario: example
   GivenScenario setup
  ...

I initially thought this was a great feature (as mentioned in Rspec stories from the trenches). However when I was using GivenScenario I was thinking as a programmer, which is usually where you start going off the tracks when writing features.

Lets look at an example of GivenScenario

 Scenario: setup
    Given an author "joe"
    And pages created by "joe":
      | title |    content   |
      | cuke  | just cuke it |

  Scenario: search pages
    GivenScenario setup
    When I search for "cuke"
    Then I should see "just cuke it" 

  Scenario: expanding search result details
    GivenScenario search pages
    When I click "show details" for the first search result
    Then I will see the author "joe"

This example highlights a number of problems with GivenScenario:

Difficult to understand isolated scenarios

While the example might make sense when working sequential through the scenarios in the longer term it produces scenarios that are hard to maintain and understand. Often during the life cycle of a system you will come back to an isolated scenario but in this example you would have to trace through the stack of scenarios to understand the context.

Creating setups which pretend to be scenarios

When creating a Scenario to use in GivenScenario often what you are actually expressing is a setup block and not a true scenario.

Noise in the output

If you re-use scenarios that contain the normal Given/When/Then it introduces a lot of noise in the output of the features. This is especially the case with multiple ‘Then’s each testing different concepts. Running our example above outputs:

  ...
  Scenario: expanding search result details
    Given an author "joe"
    And pages created by "joe"
      | title |    content   |
      | cuke  | just cuke it |
    When I search for "cuke"
    Then I should see "just cuke it"
    When I click "show details" for the first search result
    Then I will see the author "joe"
  ...

Ugly Camel case

Since the reserved word Given was already used we ended up with GivenScenario. Something that was not natural for non-technical users.

Summary

GivenScenarios are like procedure calls but from this analogy they ended up with something that had too much power. This lead to a feature which was easy to misuse and did not cleanly fit with Scenarios and plain text.

Solutions to GivenScenario

There are two solutions to replace ‘GivenScenario’:

Calling Steps from Step Definitions

The ability to call existing steps from step definitions allows us to introduce a hierarchy of abstraction in our steps.

We can have a high level Step:

  Given a basic site  

Which in turn uses our other steps.

 Given /a basic site/ do
    Given 'an author "joe"'
    Given 'pages created by "joe"', table(%{
      | title |    content   |
      | cuke  | just cuke it |
    })
  end

In contrast to ‘GivenScenario’ this solution pushes the logic down into the step definitions, moving it out of the customers domain and into the developers domain.

This reduces the noise in the feature text allowing us to focus on the real feature and value.

However abstraction is not always the right pattern when trying to add context to your features. There is a danger that high-level steps could lead to confusion, since it pushes details out of sight of the customer.

Background

Background defines of a set of steps which are implicitly run before every scenario.

This is similar to ‘GivenScenario’ but has some key differences which help overcome some of the problems mentioned:

  • Only one Background per feature - No chain of background dependencies are possible

  • Background has to be the first feature element in the Feature - We always know where to look for context.

  • It’s implicitly called in every scenario. - There is no extra noise in the scenarios.

  • It’s not shown in the output of each scenario (unless there are errors in the background) - There is no extra noise in the output.

Example:

 Background:
    Given an author "joe"
    And pages created by "joe"
      | title |    content   |
      | cuke  | just cuke it |

  Scenario: search pages
    When I search for "cuke"
    Then I should see "just cuke it" 

  Scenario: expanding search result details
    When I search for "cuke"
    And I click "show details" for the first search result
    Then I will see the author 'joe'

Comments