Search code examples
cucumbercucumber-jvmgherkin

Reusing gherkin steps with cucumber


As I understand it based on this Given When Then wiki page, Given steps interact with the app to set the precondition state, When steps interact with the app to attempt to set the desired new state being tested, and Then statements read the state of the app without modifying it.

Is reusing When steps as Given steps for subsequent states a good idea?

For instance, in a simple shopping cart application, I might write:

Given the user is interested in some item
When the user adds the item to their cart
Then the cart will include the item

Given the user adds the item to their cart
When the user checks out
Then the user will see a summary of their purchase including the item

Given the user checks out
When the user cancels an item
Then the item should be canceled
And the user should be refunded

There is a similar question here reusing the user's previous interaction in a wizard, but it seems to disagree with Uncle Bob's finite-state-machine interpretation in that the answer suggests making the steps much less rigorous, while Uncle Bob implies that the steps ought to be rigorous enough to make an intelligible state transition diagram out of them. I completely accept the advice to remove all the user-interface jargon from them and focus only on business terms, but there does seem to be a difference between logically connecting business terms as I have tried to do here, and just making logically unconnectable steps that are only connected by "unseen" glue code.


Solution

  • You're correct in that Gherkin scenarios describe steps that Arrange, Act, and Assert within the application under test.

    Uncle Bob's finite state machine can be described in Gherkin, if you have enough Gherkin statements. It's important to remember, though, that each scenario in Gherkin starts from the initial state, not from the state at the end of the scenario located above it in a feature file.

    To rephrase, each scenario MUST stand on its own.

    The potential duplication of test steps is of less importance than describing a complete scenario. One reason is that test runners may selectively run scenarios, which would cause test failures if the precursor scenario was not executed. Other test runners may run scenarios in parallel, which would also play havoc if such dependencies were allowed.

    It's perfectly acceptable, and common practice, to have a Given step repeated in several scenarios.

    Your example would be more properly stated something like:

    Given the user is interested in some item
    When the user adds the item to their cart
    Then the cart will include the item
    
    Given the user has added an item to their cart
    When the user checks out
    Then the user will see a summary of their purchase including the item
    
    Given the user purchases an item
    When the user cancels the item
    Then the item should be canceled
    

    The third Given statement could include steps in its definition to have the user put the item in the cart and check out, although it could also simply create an invoice from scratch. That's the beauty of Gherkin: it doesn't matter how the precondition is implemented, the verification is that the action causes the expected outcome.