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'