Is it ok to have multiple groups of Given/When/Then in a single gherkin scenario

Geoffrey Hing picture Geoffrey Hing · Oct 16, 2013 · Viewed 34.1k times · Source

I'm writing acceptance tests in Gherkin where I want to test for multiple changes in the UI of a web app based on an initial action. Here's an example:

        Scenario: Cancel editing a new text asset
            Given the user "[email protected]" is logged in
            When the user navigates to "/build/"
            And the user clicks the "Sandbox" link
            And the user inputs "Test story for canceling editing of a new text asset" for the "title" field
            And the user inputs "Test User" for the "byline" field 
            And the user inputs "My summary, so exciting!" for the "summary" textarea
            And the user clicks on "Untitled Section" in the section list
            And the user clicks the "Text" icon in the "center" container 
            And the user inputs the following text in the rich text editor:
                    """
                    Test text for asset. This is cool. 
                    """
            And the user clicks the "cancel" button
            Then the following text is not present: 
                    """
                    Test text for asset. This is cool. 
                    """
            And the "Image" icon is present
            And the "Text" icon is present
            When the user refreshes the browser 
            And the user clicks on "Untitled Section" in the section list
            Then the following text is not present:
                    """
                    Test text for asset. This is cool. 
                    """
            When the user opens the asset drawer
            Then the following text is not present:
                    """
                    Test text for asset. This is cool.
                    """

Note that there are multiple groups of When/Then steps, to test for responses of the initial action. While most implementations of steps ignore the prefix keyword, and I'm pretty sure that I can get this test to run, is there a better way to test the different outcomes? Is it better practice to write multiple scenarios with the same setup but different "Then" statements?

Answer

Michael Szymczak picture Michael Szymczak · Oct 16, 2013

Remember that you should test only ONE behaviour/feature at a time. The rule of thumb is that you should use only one When step:

Given some state before action
  And some other state before action
  ...
When  only one action
Then  assert correct output
  And assert correct output
  ...

You see - only one line of When, without any Ands under When. If you use many When steps instead, you create test script, not a specification. Your tests will be hard to understand and you will notice that you add more and more steps when the underlying implementation changes.

You also need to keep underlying logic hidden, because you don't want to change it every time you change something irrelevant. Example:

And the user inputs "My summary, so exciting!" for the "summary" textarea

What if you change the summary field from a textarea to an input type? You have to change the scenario (maintenance nightmare) or left you scenario lying (worse than not having scenario). You should write instead:

When the user describes it as "so exciting!"

But still, the structure of the whole scenario is bad. Ask yourself the question: what I want to check? If I were a person that wants to understand the business logic of the feature I would like to see something like:

Scenario: Cancel editing a new text asset
  Given I edit the Sandbox details with some data
  When  I cancel editing
  Then  Sandox details should be empty

That's it!

How to achieve it? Move all irrelevant logic deeper, use the PageObject pattern etc. And read about Specification By Example