Reusing Textual Stories

BDD encourages the description of the acceptance tests in a manner that is intelligible and transparent to the business users. This in particular may mean setting up explicitly via a series of scenario steps all the pre-requirements of a particular story or scenario. For complex scenarios this will rapidly lead to maintenance problems due to duplication of entire blocks of steps.

To help the user better manager more complex scenarios, JBehave allow the specification of entire stories as a pre-requisite for another story or scenario.

    !-- A precondition to entire story
    GivenStories: path/to/precondition1.story

    Scenario:  A scenario in which the user can run additional stories as pre-requisites

    !-- preconditions to scenario    
    GivenStories: path/to/precondition2.story,
    Given ... // normal scenario steps

When JBehave encounters the keyword GivenStories, it will run the (one or more) textual stories specified by path in the list (using the same Steps instances specified for the parent story) before proceeding to the execution of the scenarios (if at story level) or scenario steps (if at scenario level).

Another way to avoid duplication of textual scenario steps is to use the natural ordering of execution of the story classes. Typically, this means that the stories will be executed in the alphabetical order of their names and a convention can be adopted to have stories start with an alpha-numerical prefix, such as 'Snn' where 'nn' is an incremental number. This though has the disadvantage of having to run all stories leading up to the desired scenario, which in some cases can be unnecessary and time consuming. For example, for debugging purposes one may need to one run one scenario, which may have a dependency on just one other story. This is where GivenStories is most useful.

GivenStories filtered by scenario meta parameters

At times, it's useful only to depend on one or two scenarios of a story, and not the entire story. In this case, we can use an anchor in the story path to filter the scenarios that need to be executed. The scenarios will be filtered using meta parameters defined in the scenarios:

    GivenStories: path/to/precondition.story#{id1:scenario1;id2:scenario2}

The precondition.story could e.g. contain three scenarios, of which we want to execute only the first two:

    Scenario:  Scenario 1
    Meta: @id1 scenario1
    Given ... // scenario executed as a precondition

    Scenario:  Scenario 2
    Meta: @id2 scenario2
    Given ... // scenario executed as a precondition

    Scenario:  Scenario 3
    Meta: @id3 scenario3
    Given ... // scenario not executed as a precondition

GivenStories parametrized by Examples

In the spirit of avoid unnecessary duplication, it useful at times to allow parametrization of given stories, i.e. executing them with different sets of parameters. Parametrized given stories work on the same principles of parametrized scenarios, using parameter injection. The only thing that differs with the case of parametrized scenarios is the convention by which the parameter sets are provided.

GivenStories parametrized by Meta

One way to parametrise the given stories is use the Meta: keyword:

    Meta: @One uno @Two due
    GivenStories: path/to/precondition.story
    Scenario:  A scenario which is executed after the parametrised story-level given stories
    Given ... // normal scenario steps

GivenStories parametrized by Examples

Another way is to use the Examples: keyword to collect the sets of parameters, allowing the user to provide via an anchor, an optional appendix of the form #{row} to the story path, which is interpreted as row number of the parameters to inject in the story execution.

For example, if we want to execute the same given story with two different sets of parameters, specified as the first and second row of the examples table:

    Scenario:  A scenario in which the user can run other stories as pre-requisites
               parametrized using the rows of the Examples table
    GivenStories: path/to/precondition.story#{0},
    Given ... // normal scenario steps

Conventionally, if the examples table is used to parametrized the GivenStories (i.e. if anchors are present in the story paths), it is assumed we are not using it to parameterize the scenario at the same time. This behaviour may be made configurable in the future, depending on the need.

Notes: The full path can be omitted if the GivenStories file is in the same directory as the story referring to it. The GivenStories file does not have to follow the naming conventions of the rest of the stories in your suite.