Solving: Selecting between Given and When #GivenWhenThenWithStyle

Last week, you voted for different ways of capturing the intent of a scenario, particularly when the same piece of information can belong to a title, a Given step or a When step. This article shows the results of the survey, an analysis of the votes, and some general ideas on how to decide where to place details in a Given-When-Then scenario.

The winner is…

The community overwhelmingly voted for the option to explicitly state the action in the When step – more than three quarters of participants selected that option. Here are some reasons behind that choice:

  • Faith Peterson wrote that this helps clarity by separating the action from the outcome
  • Marco Beelen likes that option because “calculation of the gross price is the unit under test”, and showing it in a separate When statement makes it clear what is being tested.
  • Lada Flac choose that option because the “case is complete, clearly describes the starting and ending point and the trigger needed to get to the end result.”
  • David Evans suggested that ‘even though it is a little more verbose, every scenario should have a “When” clause that explicitly identifies the action of interest’

As downsides of the remaining options, many people pointed out that skipping a Given step doesn’t let people easily understand the context, and that mixing information in Given and When steps confuses inputs and actions. (Several people, though, liked when everything is bundled in the When step, as it keeps it simple.)

My choice would be slightly different from the community votes. But let’s unpack first what makes a good structure for a scenario.

What makes a good structure?

The explanations for the votes, again, are probably more important for this discussion than the votes themselves.

Having an explicit When step helps to show clearly what is being tested, and separates the action from the outcome, as well as separating the inputs from the action. On the other hand, things also need to be simple. And we need to balance simplicity with consistency.

For me, a scenario structure is good if it fulfils these three roles:

  1. Clarify the relationship between inputs and outputs
  2. Clarify what’s actually being tested
  3. Help people focus on important aspects of the objects under test

The first role requires getting Given and Then right, since they relate to inputs and outputs.

The second role is usually in the When step, but (I’ll argue about this in a moment) it doesn’t necessarily have to be there.

The third role requires getting rid of extraneous information that is not directly related to a particular scenario.

Clarify the relationship between inputs and outputs

One of the best aspects of Given-When-Then is that it sounds almost like regular human language, with just enough structure to help guide the discussions. However, natural language is ambiguous, and human conversation often includes redundancy and additional context to help us clarify the intent. With Given-When-Then scenarios, we want precision and not ambiguity. We want to avoid redundancy that could create confusion and problems in maintenance. But because Given-When-Then sounds almost like regular human language, people often fall into the trap of mixing up GivenWhen and Then clauses.

In English, and my guess is in most other human languages, the following three statements would mean the same thing:

  • Given I try to make a purchase of 20 EUR, when I have a credit card, …
  • Given I have a credit card, when I try to make a purchase of 20 EUR, …
  • When I have a credit card, then I try to make a purchase…

From an analysis perspective, these cases describe completely different scenarios, with different boundaries and key examples that would come after collaborative analysis.

In the first case, I’d expect card operations to be under test (since this is in the When), and other related scenarios would try different types of operations. For example chargebacks, authorisations without capture, refunds, payouts and so on.

In the second case, I’d expect the purchase process to be under test (since that is in the When), and other related scenarios would try out the purchase process with different types of payment instruments – for example bank transfer, e-wallets, direct debits, invoice payments and so on.

The third case is just confused, although it does sound OK in a regular sentence, it’s not a good scenario.

To create good scenarios, we need to avoid the trap of Given/When/Then sounding too much like a natural language, and allowing ambiguity. Here are three quick techniques that can help you clarify what should go where:

  • Phrase scenarios in past/present/future
  • Avoid data in the When step
  • Use the Passive/Active/Passive structure

Past/Present/Future

The first technique I like to use for clarifying what’s an input, what’s an output and what we’re testing is to use different tenses.

Most of the examples you can see online and in books are all written in present tense. When everything in the sentence happens at the same time, then people can easily mix up inputs and outputs and the action under test, and it will still sound OK. Human language intentionally has this flexibility. But when things happen at different times, it’s easier to spot inconsistencies. “Given I tried to make a purchase, when I have a credit card” just sounds a bit off. You need to have some way of paying before trying to make a purchase.

Structure the scenarios in three different tenses and you’ll get subtle hints to fix the structure. Put Given steps in the past, When steps in the present and Then steps in the future. Now I’m not suggesting dusting off your old grammar books and figuring out how to phrase things in Future Perfect Continuous Tense. Keep it simple.

If you like writing in present tense, then use this technique to just mentally check if things sound OK if they would be placed in different times.

Avoid data in the When step

When step that contains data is a big warning sign. It’s not always wrong, but in most cases this means that a scenario is confusing the action under test with either inputs or outputs.

Ideally, for a group of related scenarios, the When statement should be the same. If that step contains some data, instead of just describing an action, then readers will not be able to easily judge how changing a When parameter affects the scenario.

Consider the following step: When the user makes a purchase for $200. Does a purchase for $199 create just another example belonging to the same case, or is it a genuinely different scenario? It’s difficult to tell.

Putting data into the When step makes it hard to decide on the right boundaries to test, and understand what kind of examples belong to the same scenario. When all the data is either in the Given or Then steps, then boundaries are easier to find and inspect.

Passive/Active/Passive

The third useful technique is to phrase Given and Then with passive verbs and When with active verbs.

Given and Then should explain the state of the world (or the system under test) without the details of how we got there. Given a registered user with two items in a shopping cart is much more focused and direct than explaining a chain of actions that led to someone signing in, searching and adding items to a shopping cart and checking out. Likewise, Then the purchase status should be “declined” is much clearer than talking about dialogs popping up, the user dismissing warnings or an admin reading an inventory report.

If you find yourself writing an active verb in the Given part, try first rephrasing it so it is passive. If it doesn’t fit, then the action you want to write really belongs in the When step. The same goes for active verbs in the Then steps.

Similarly, passive verbs in the When step suggest that we’re still setting up the context, or starting to check for post-conditions.

Clarifying the action under test

This brings me back to the original question. What if there is no specific active verb that we can use in the When step?

This probably goes against most of the advice you’ll find online (and against the way the community voted this time), but I’m not particularly worried if a scenario is missing a “When” statement.

The key question is whether the scenario makes the action under test obviously clear. In many cases the When statement is the right place to explain that aspect. However, if the title of the scenario already fulfils that role, there’s a big question if it should be duplicated.

For the purpose of understanding the action under test, a good title is more important than a good When statement. A scenario with a good title and a bad or a missing When statement is still easy to understand. A scenario with a good When statement but a bad or missing title is just going to create problems in the future, since people will not know if the scope of the scenario is right or wrong.

The original format for capturing examples in executable specifications did not have an explicit When step. FIT tables usually captured the scope of test in a table title, and then provided inputs and outputs in the table columns. With the right title in the table, this worked perfectly fine. The problem in many cases was that people didn’t bother capturing the title correctly, but instead listed automation component names in FIT table titles, ensuring that the readers will be totally confused. Given/When/Then format introduced just enough structure to avoid those common problems, which is why it’s so popular today.

If the When statement is not bringing anything additional apart from the information already in the title, I don’t see much point in keeping it. In fact, duplicating the information in the title and the scenario makes it more error prone. People might modify it in one place in the future, but forget to change it in another.

Of course, this is fully a question of style. Some people prefer to duplicate information for the sake of consistency, which is a perfectly valid argument. I prefer simpler scenarios where information is not duplicated unnecessarily. At the end, this comes down to balancing the forces that affect the three roles I listed earlier. Removing redundant information helps to keep things simple and provide focus. Explicitly following a structure helps to clarify that is being tested.

Stay up to date with all the tips and tricks and follow SpecFlow on Twitter or LinkedIn.

PS: … and don’t forget to share the challenge with your friends and team members by clicking on one of the social icons below 👇