Howard Paget
Projects
About

Writing Better Tests: Consider using Given, When, Then

Jun 14, 2022
testing

This article is part of a series about writing good tests go to the article listing all tips here.

In this article we will discuss a way of laying out tests such that they reveal and document the use cases of the class/module/application. The structure follows the behaviour driven development (BDD) “Given, When, Then” pattern used to specify acceptance criteria.

  • Given: some initial state.
  • When: something is called or triggered.
  • Then: some statements that are expected to be true.

Additional Given and Then statements can be added with “And” as seen in the code example below.

Example

Let’s apply the pattern to a test of withdrawing £40 from a balance that contains £100.

  • Given: a balance amount of £100.
  • When: £40 is withdrawn.
  • Then: the current balance is £60
  • And: the latest transaction is the £40 withdrawal.

In code we might write:

// Given: a balance with an initial amount of £100
Balance balance = new Balance(100);

// When: £40 is withdrawn from the balance
balance.withdraw(40);

// Then: balance remaining is £60
assertThat(balance.getAmount()).isEqualTo(60);

// And: most recent transaction is a withdrawal of £40
assertThat(balance.getTransaction(0).getType()).isEqualTo(WITHDRAWAL);
assertThat(balance.getTransaction(0).getAmount()).isEqualTo(40);

The result is a test that clearly documents the behaviour of the withdraw method in the case of the withdrawal being less than the current balance amount. A collection of similarly written tests would provide examples of all use tests of the Balance class.

It should be noted that this structure may be overkill for simple or very fine-grained tests for example a function that converts a string to title case.