Article

Background , Data Tables, Scenario Outlines

Dec 19, 2021

A background section in a feature file allows you to specify a set of steps that
are common to every scenario in the file. Instead of having to repeat those

steps over and over for each scenario, you move them up into a Background
element. Here are a couple of advantages to doing this:
• If you ever need to change those steps, you have to change them in only
one place.
• The importance of those steps fades into the background so that when
you’re reading each individual scenario, you can focus on what is unique
and important about that scenario.
To show you what we mean, let’s take an existing scenario that uses only the
basic Gherkin Scenario element and improve its readability by refactoring it to
use a Background. Here’s our feature before the refactoring starts:

Feature: Change PIN
Customers being issued new cards are supplied with a Personal
Identification Number (PIN) that is randomly generated by the
system.


In order to be able to change it to something they can easily
remember, customers with new bank cards need to be able to
change their PIN using the ATM.


Scenario: Change PIN successfully
Given I have been issued a new card
And I insert the card, entering the correct PIN
When I choose "Change PIN" from the menu
And I change the PIN to 9876
Then the system should remember my PIN is now 9876


Scenario: Try to change PIN to the same as before
Given I have been issued a new card
And I insert the card, entering the correct PIN
When I choose "Change PIN" from the menu
And I try to change the PIN to the original PIN number
Then I should see a warning message
And the system should not have changed my PIN

You can see that there are two scenarios here, but without reading them
carefully, it’s quite hard to see what exactly is going on in each one. The first
three steps in each scenario, while necessary to clarify the context of the
scenario, are completely repeated in both scenarios. That repetition is distracting,
making it harder to see the essence of what each scenario is testing.
Let’s factor out the three repeated steps into a Background, like this:

Feature: Change PIN
As soon as the bank issues new cards to customers, they are
supplied with a Personal Identification Number (PIN) that
is randomly generated by the system.


In order to be able to change it to something they can easily
remember, customers with new bank cards need to be able to
change their PIN using the ATM.


Background:
Given I have been issued a new card
And I insert the card, entering the correct PIN
And I choose "Change PIN" from the menu


Scenario: Change PIN successfully
When I change the PIN to 9876
Then the system should remember my PIN is now 9876
Scenario: Try to change PIN to the same as before
When I try to change the PIN to the original PIN number
Then I should see a warning message
And the system should not have changed my PIN

Our refactoring hasn’t changed the behavior of the tests at all: at runtime,
the steps in the background are executed at the beginning of each scenario,
just as they were before. What we have done is made each individual scenario
much easier to read.
You can have a single Background element per feature file, and it must appear
before any of the Scenario or Scenario Outline elements. Just like all the other
Gherkin elements, you can give it a name, and you have space to put a multiline
description before the first step. For example:

Feature: Change PIN
In order to be able to change it to something they can easily
remember, customers with new bank cards need to be able to
change their PIN using the ATM.


Background: Insert a newly issued card and sign in
Whenever the bank issues new cards to customers, they are supplied
with a Personal Identification Number (PIN) that is randomly
generated by the system.


Given I have been issued a new card
And I insert the card, entering the correct PIN
...

Using a Background element isn’t always necessary, but it’s often useful to
improve the readability of your features by removing repetitive steps from
individual scenarios. Here are some tips for using it well:
• Don’t use Background to set up complicated state unless that state is
something the reader actually needs to know. For example, we didn’t
mention the actual digits of the system-generated PIN in the previous
example, because that detail wasn’t relevant to any of the scenarios.
• Keep your Background section short. After all, you’re expecting the user to
actually remember this stuff when reading your scenarios. If the background
is more than four lines long, can you find a way to express that
action in just one or two steps?
• Make your Background section vivid. Use colorful names and try to tell a
story, because your readers can keep track of stories much better than
they can keep track of dull names like User A, User B, Site 1, and so on.
If it’s worth mentioning at all, make it really stand out.
• Keep your scenarios short, and don’t have too many. If the Background is
more than three or four steps long, think about using higher-level steps
or splitting the feature file in two. You can use a background as a good
indicator of when a feature is getting too long: if the new scenarios you
want to add don’t fit with the existing background, consider splitting the
feature.
• Avoid putting technical details such as clearing queues, starting backend
services, or opening browsers in a background.

Data Tables

Sometimes steps in a scenario need to describe data that doesn’t easily fit on
a single line of Given, When, or Then. Gherkin allows us to place these details in
a table right underneath a step. Data tables give you a way to extend a Gherkin
step beyond a single line to include a larger piece of data.
For example, consider these steps:

Refactoring to Background
Refactoringa is the process of changing code to improve its readability or design
without changing its behavior. This technique applies to Gherkin features just as
well as it does to the rest of your codebase. As your understanding of your domain
grows through the course of the project, you’ll want to reflect that learning by
updating your features.
Often you don’t see a background immediately. You might start out by writing one
or two scenarios, and it’s only as you write the third that you notice some common
steps. When you spot a feature where the same or similar steps are repeated in several
scenarios, see whether you can refactor to extract those steps into a background.
It can take a little bit of courage to do this, because there’s a risk you might make a
mistake and break something, but this is a pretty safe refactoring. Once you’re done,
you should end up with the feature doing exactly the same thing as it did before you
started but easier to read.

 

Given a User "Michael Jackson" born on August 29, 1958
And a User "Elvis" born on January 8, 1935
And a User "John Lennon" born on October 9, 1940
...

Boring! We wouldn’t tolerate this kind of repetitive stuff in a traditional
specification document, and we don’t have to tolerate it in a Cucumber
specification either. We can collect those steps together into a single step that
uses a table to express the data:

Given these Users:
| name                      | date of birth |
| Michael Jackson    | August 29, 1958 |
| Elvis                       | January 8, 1935 |
| John Lennon          | October 9, 1940 |

That’s much clearer. The table starts on the line immediately following the
step, and its cells are separated using the pipe character: |. You can line up
the pipes using whitespace to make the table look tidy, although Cucumber
doesn’t mind whether you do; it will strip out the values in each cell, ignoring
the surrounding whitespace.
In the previous table, we’ve used a heading for each column in the table, but
that’s only because it made sense for that particular step. You have the freedom
to specify data in different ways, such as putting the headings down the
side:

Then I should see a vehicle that matches the following description:
| Wheels           | 2 |
| Max Speed     | 60 mph |
| Accessories    | lights, shopping basket |


Or just to specify a list:
Then
my shopping list should contain:
| Onions        |
| Potatoes     |
| Sausages   |
| Apples        |
| Relish         |


To explain how to work with these different shaped tables, we need to take a
short dive down into the step definition layer. If you’re not interested in writing
Java step definition code, feel free to skip this bit.


Working with Data Tables in Step Definitions
We’ll illustrate how to use a data table in your step definitions with a quick
game of tic-tac-toe. Let’s imagine we’re building a tic-tac-toe game and we’ve
started working on the basic feature for making moves on the board. We start
with a scenario like this:

expressive_scenarios/01/src/test/resources/tic_tac_toe/tic_tac_toe.feature
Feature
:
     Scenario:
        Given a board like this:
|         | 1 | 2 | 3 |
| 1      |    |    |    |
| 2      |    |    |    |
| 3      |    |    |    |
When player x plays in row 2, column 1
Then the board should look like this:
|    | 1 | 2 | 3 |
| 1 |    |    |    |
| 2 | x |    |    |
| 3 |    |    |    |
We’ll show you how to grab the table from the first step, manipulate it in the
second, and finally compare the expected board from the scenario with the
actual one.
Run ./cucumber to generate the step definition snippets, and paste them into
step_definitions/BoardSteps.java:

 

expressive_scenarios/01/src/test/java/tic_tac_toe/BoardSteps.java
package tic_tac_toe;
import cucumber.api.java.en.*;
import cucumber.api.PendingException;
import cucumber.api.DataTable;
public class BoardSteps {
@Given("^a board like this:$")
public void aBoardLikeThis(DataTable arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
// For automatic transformation, change DataTable to one of
// List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
// E,K,V must be a scalar (String, Integer, Date, enum etc)
throw new PendingException();
}
@When("^player x plays in row (\\d+), column (\\d+)$")
public void playerXPlaysInRowColumn(int arg1, int arg2) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
@Then("^the board should look like this:$")
public void theBoardShouldLookLikeThis(DataTable arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
// For automatic transformation, change DataTable to one of
// List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
// E,K,V must be a scalar (String, Integer, Date, enum etc)
throw new PendingException();
}
}

Notice that the snippets for the two step definitions where we’re going to
receive a table are a little different. There’s a comment telling you about
automatic conversion of the DataTable argument you’re being passed, but we’ll
ignore that for now (don’t worry—we’ll talk a lot about automatic conversion
later). The cucumber.api.DataTable is a really rich object with lots of methods for
interacting with its data. We’ll show you some of the most useful ones now.
Let’s start fleshing out those step definitions.


Turning the Table into a List of Lists
Under the hood, the table is just a List of Lists of Strings: List<List<String>>. Often
we’ll want to work with it in that raw form, so we can call the raw method on
it to do just that. Let’s get the raw data from the table and store it in an
instance variable board, which we can manipulate in our second step when
we want to make a move.

As an experiment, add an implementation for the second step definition that
just prints the raw board out so we can see what it looks like:


expressive_scenarios/02/src/test/java/tic_tac_toe/BoardSteps.java
package tic_tac_toe;
import cucumber.api.java.en.*;
import cucumber.api.PendingException;
import cucumber.api.DataTable;
import java.util.List;
public class BoardSteps {
private List<List<String>> board;
@Given("^a board like this:$")
public void aBoardLikeThis(DataTable table) throws Throwable {
this.board = table.raw();
}
@When("^player x plays in row (\\d+), column (\\d+)$")
public void playerXPlaysInRowColumn(int arg1, int arg2) throws Throwable {
System.out.println(board.toString());
throw new PendingException();
}
@Then("^the board should look like this:$")
public void theBoardShouldLookLikeThis(DataTable arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
// For automatic transformation, change DataTable to one of
// List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
// E,K,V must be a scalar (String, Integer, Date, enum etc)
throw new PendingException();
}
}

When you run ./cucumber, you should see the two-dimensional array printed.
$ ./cucumber

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running RunCukesTest
Feature:
[[, 1, 2, 3], [1, , , ], [2, , , ], [3, , , ]]
Scenario: # tic_tac_toe/tic_tac_toe.feature:2
Given a board like this:
When player x plays in row 2, column 1
cucumber.api.PendingException: TODO: implement me
at tic_tac_toe.BoardSteps.playerXPlaysInRowColumn(BoardSteps.java:21)
at *.When player x plays in row 2, column 1(tic_tac_toe.feature:8)
Then the board should look like this:
1 Scenarios (1 pending)
3 Steps (1 skipped, 1 pending, 1 passed)

 

 

 

 

 

 

 

 

Other Article

What is the Cucumber Scenario Outline?

A Powerful Tool for Efficient and Effective Test Automation

Gmail Automation using Selenium

Gmail Automation

Writing User Stories With Gherkin

Gherkin is a structured approach to writing behavioral tests

Background , Data Tables, Scenario Outlines

A background section in a feature file allows you to specify a set of steps that are common to every scenario in the file.

Most Important Things Automation Engineers Should Know

I mentioned here some of the common mistakes that automation engineers produce in their work, and ways to avoid those mistakes.

Database Testing - JDBC

We need to access Databases from outside(Intellij, Eclipse etc ) of SQL developer to test