A more polished version of this article is in my book Fifty Quick Ideas To Improve Your Tests
Behaviour-driven development is becoming increasingly popular over the last few years, and with it the Given-When-Then format for examples. In many ways, Given-When-Then seems as the de-facto standard for expressing functional checks using examples. Introduced by JBehave in 2003, this structure was intended to support conversations between teams and business stakeholders, but also lead those discussions towards a conclusion that would be easy to automate as a test.
Given-When-Then statements are great because they are easy to capture on whiteboards and flipcharts, but also easy to transfer to electronic documents, including plain text files and wiki pages. In addition, there are automation tools for all popular application platforms today that support tests specified as Given-When-Then.
On the other hand, Given-When-Then is a very sharp tool and unless handled properly, it can hurt badly. Without understanding the true purpose of that way of capturing expectations, many teams out there just create tests that are too long, too difficult to maintain, and almost impossible to understand. Here is a typical example:
Scenario: Payroll salary calculations Given the admin page is open When the user types John into the 'employee name' and the user types 30000 into the 'salary' and the user clicks 'Add' Then the page reloads And the user types Mike into the 'employee name' and the user types 40000 into the 'salary' and the user clicks 'Add' When the user selects 'Payslips' And the user selects employee number 1 Then the user clicks on 'View' When the user selects 'Info' Then the 'salary' shows 29000 Then the user clicks 'Edit' and the user types 40000 into the 'salary' When the user clicks on 'View' And the 'salary' shows 31000
This example might have been clear to the person who first wrote it, but it’s purpose is unclear – what is it really testing? Is the salary a parameter of the test, or is it an expected outcome? If one of the bottom steps of this scenario fails, it will be very difficult to understand the exact cause of the problem.
Spoken language is ambiguous, and it’s perfectly OK to say ‘Given an employee has a salary …, When the tax deduction is…, then the employee gets a payslip and the payslip shows …’. It’s also OK to say ‘When an employee has a salary …, Given the tax deduction is …’ or ‘Given an employee … and the tax deduction … then the payslip …’. All those combinations mean the same thing, and they will be easily understood within the wider context.
But there is only one right way to describe those conditions with Given-When-Then if you want to get the most out of it from the perspective of long-term test maintenance.
The sequence is important. ‘Given’ comes before ‘When’, and ‘When’ comes before ‘Then’. Those clauses should not be mixed. All parameters should be specified with ‘Given’ clauses, the action under test should be specified with the ‘When’ clause, and all expected outcomes should be listed with ‘Then’ clauses. Each scenario should ideally have only one When clause, that clearly points to the purpose of the test.
Given-When-Then is not just an automation-friendly way of describing expectations, it’s a structural pattern for designing clear specifications. It’s been around for quite a while under different names. When use cases were popular, it was known as Preconditions-Trigger-Postconditions. In unit testing, it’s known as Arrange-Act-Assert.
Using Given-When-Then in sequence is a great reminder for several great test design ideas. It suggests that pre-conditions and post-conditions need to be identified and separated. It suggests that the purpose of the test should be clearly communicated, and that each scenario should check one and only one thing. When there is only one action under test, people are forced to look beyond the mechanics of test execution and really identify a clear purpose.
When used correctly, Given-When-Then helps teams design specifications and checks that are easy to understand and maintain. As tests will be focused on one particular action, they will be less brittle and easier to diagnose and troubleshoot. When the parameters and expectations are clearly separated, it’s easier to evaluate if we need to add more examples, and discover missing cases.
How to make it work
A good trick, that prevents most of accidental misuse of Given-When-Then, is to use past tense for ‘Given’ clauses, present tense for ‘When’ and future tense for ‘Then’. This makes it clear that ‘Given’ statements are preconditions and parameters, and that ‘Then’ statements are postconditions and expectations.
Make ‘Given’ and ‘Then’ passive – they should describe values rather than actions. Make sure ‘When’ is active – it should describe the action under test.
Try having only one ‘When’ statement for each scenario.