Write beautiful test cases with Gherkin

There are many ways to write test cases, but the Gherkin language holds a special place in my QA heart :). But before explaining its philosophy, let’s first analyze how a test case is usually written, to better understand what Gherkin brings to the table.

Test cases fundations

The classic method of writing test cases is based on a sequence of (action, result) pairs. Each of these actions specifies exactly all the steps the tester needs to perform (every click, every swipe, every text to type, etc.). For example:

ActionExpected result
click hereoverlay opens
Enter text "foo" in field NameText is well displayed
Click on the checkbox "bar"Checkbox is ticked
etc...etc...

This highly detailed method ensures that anyone can follow the procedure (including someone who didn’t write it). However, these procedures are:

  • long and tedious to read,
  • cumbersome to update,
  • too closely tied to the User Interface (UI).

As a result, even the slightest graphical change can require updating multiple lines of these procedures, always with the risk of missing one since there’s no common structure shared between test cases.

Additionally, these test cases are often stored in tools exclusively managed by QA. Other team members typically only have access to test reports (which they often only look at to see the failure percentage), further isolating testers from the rest of the team.

Let’s take an example using a dating app. A test case representing a match between two people could be written like this:

actionresult
On device 1, as user 1, search for people to meet nearbyfind the user 2
On device 1, as user 1, send a like to user 2a heart should be displayed
On device 2, as user 2, a notification should be received
On device 2, as user 2, click on the notificationThe app opens and display the profile of user 1
On device 2, as user 2, swipe on the left to accept the requestUser 1 receives a notification for a match.
User 1 and user 2 should be able to talk to each other

While this table is understandable on its own, it’s easy to see how this would no longer be the case with hundreds of test cases (user1 doesn’t like user2, user2 doesn’t accept user1’s like, etc.). Additionally, readability is lost because the important information (the test case in the last row) is buried among contextual details.

How to write readable test cases?

The first step is to distance ourselves from the UI and focus solely on testing the functionality. Thus, our previous example could be written like this:

If user1 sends a like to user2, and user2 accepts the request, then user1 should receive a notification and both users should be able to chat.

Here, we’ve kept only what’s functionally important (initial situation, action, result) and removed all the unnecessary details. Additionally, we’ve detached from graphical choices (it doesn’t matter whether you swipe left, right, etc.). We gain clarity, and someone new to the company could easily read this test case and understand the purpose of the functionality.

Gherkin language

The Gherkin language is an implementation of Behaviour Driven Development (BDD). This programming method aims to enhance communication among team members (the “3 amigos,” discussed in another article, is another implementation of this). Gherkin focuses on testing functionality without excluding QA from the rest of the team. It’s based on four main keywords (I say “main” because there are a few more than four):

  • Given: describes the initial situation, usually phrased in the passive voice or past tense.
  • When: describes the action, using an action verb in the present tense.
  • Then: describes the result, and includes “should” to indicate the expected outcome.
  • And: repeats the keyword from the previous line (useful when there are multiple conditions to check).

If we revisit the previous example, we get this:

Given user1 sent a like to user2
When user2 accepts the request from user1
Then user1 should receive a notification
And user1 and user2 should be able to chat

Now, we have a precise and concise test case. It can be understood (and executed) by both a developer and a Product Owner. Even better, it can be easily automated and helps move towards living documentation (teaser for an upcoming article).

Best practices and pitfalls

Although it’s not mandatory, I recommend following the verb tenses indicated above: this will help you maintain consistency in your writing and make your test cases easier to read.

A test case is different from a user journey. Therefore, we should avoid chaining multiple (When/Then) pairs within a single test case (which would bring us back to the lack of readability of the old method).

Always use the same phrasing. Don’t write “Given user1 sent a like to user2” one day, and then “Given user1 liked user2” the next. One of the strengths of this language is that it can be automated. If you change the phrasing to express the same idea, you’ll end up duplicating your code, and the risk of missing updates will resurface!

We’re testing functionality, and our test cases will be automated: so try to find phrases that are at the right level to be reusable across multiple test cases. In particular, we want to avoid phrases like “When I click on that button.”

The added bonus of this language is that it promotes vocabulary standardization. In many companies, most of the terminology used to discuss the system is shared, but there are always small differences between technical and non-technical teams. With this language, which is accessible to everyone, we formalize the correct term for each feature in one place. This gradually improves communication, as everyone will start using the same vocabulary.

Leave a Reply

Your email address will not be published. Required fields are marked *