Data Tables in Cucumber BDD Framework

Shraddha Joshi
6 min readMar 20, 2023

--

Overview

Cucumber is Behavioral Driven Development Framework that allows to develop simple text based executable test scenarios. If you have worked with Cucumber BDD, then you know sometimes it is bit difficult to create readable yet functional automated tests. For example, testing with multiple datasets. In this blog, let us have a closer look at the Java Cucumber binding which is Data Tables that helps to write test scenarios with various test data.

Cucumber transforms business requirements into simple readable test scripts

Data Tables

Data Tables is a data structure provided by Cucumber. It helps you to get data from feature files to Step Definitions. It is bridge which passes values to the parameters from feature files to Step Definition. Data Tables can handle large amounts of data. Data can be passed as one-dimensional data, as two-dimensional data and also in form of key-value pair.

Data tables are often misunderstood with Example tables or Scenario tables which are the tables used for entire scenarios. Let us understand the difference between these two.

Scenario Outline:

· It runs for the whole test.

· Example keyword is used at the end of the Scenario to define the test data.

· The entire test is run for the number of times equal to the number of data entries in the Test set.

Example of Scenario Outline

Feature: Login Test

Scenario Outline: Successful Login with Valid Credentials

Given User is on Home Page

When User Navigate to Login Page

And User enters “<username>” and “<password>”

Then Message displayed Login Successfully

Examples:

| Username | Password |

| Employee_1 | Welc@345 |

| Employee_2 | Test@542 |

Step Definition

@When("^User enters \"(.*)\" and \"(.*)\"$")
public void user_enters_UserName_and_Password(String username, String password) throws Throwable {
driver.findElement(By.id("Username")).sendKeys(username);
driver.findElement(By.id("Password")).sendKeys(password);
//driver.findElement(By.id("Login")).click();
}

In this example, the scenario will run two times, passing in one row at each time.

Data Tables:

· It will work only for that single step under which the test data is defined.

· It is not required to use any Keyword to define the test data.

· The entire test will run once and only the step definition with test data will iterate equal to data entries. To integrate such way, a separate code is written which runs single or multiple times.

Implementation of Data Tables

Let us understand how to incorporate the Data tables in the automation code with example.

Pre-Requisite:

  1. Cucumber
  2. Java — 11
  3. Selenium
  4. Junit (You can use TestNG also)
  5. Cucumber JUnit (If using TestNG, then replace this with Cucumber TestNG)

Project Structure:

Maven project structure for implementing Data tables in Cucumber

Data tables from Gherkin can be accessed by using the DataTable object as the last parameter in a Step Definition. This conversion can be done either by Cucumber or manually. Depending on the data, we can use List and Map collections such as

· Table into List<List<String>> (List of a List of Strings)

Example:

| FirstName | LastName | Age |

| Geeta | Thomas | 40 |

| Lisa | Red | 34 |

| Mitchell | Dunphy | 36 |

java type: List<List<String>>

The normal representation of list of a list of strings is shown below.

[

[ “firstName”, “LastName”, “Age” ],

[ “Geeta”, “Thomas”, “40” ],

[ “Lisa”, “Red”, “34” ],

[ “Mitchell”, “Dunphy”, “36” ]

]

· Table into List<Map<String, String>> (List of Maps)

Example:

java type: List<Map<String, String>>

The normal representation of list of maps is shown below.

[

{ “firstName”: “Geeta”, “lastName”: “Thomas”, “age”: “40” },

{ “firstName”: “Lisa”, “lastName”: “Red”, “age”: “34” },

{ “firstName”: “Mitchell”, “lastName”: “Dunphy”, “age”: “36” }

]

· Table into Map<String, String>

Example:

Table where first column is key as shown below

| WA | Washington |

| IL | Illinois |

java type: Map<String, String>

TO convert the table into a single map

{

“WA”: “Washington”,

“IL”: “Illinois”

}

· Table into Map<String, List<String>> (Map uses list as its value)

A table with multiple column values per key.

| EmpID01 | Geeta | 02 |

| EmpID02 | Lisa | 05 |

java type: Map<String, List<String>>

{

“EmpID01”: [“Geeta”,”02"],

“EmpUD02”: [“Lisa”,”05"]

}

Let us code Data table in Cucumber using Java.

· Data tables without Headers Example:

Suppose we want to test Login page of the application. We will pass the test data with step definition.

Feature: Login with valid credentials

Scenario: Successful login with valid credentials

Given User is on the Login Page

When User enters Credentials

| Sharon2023 | Welcome@2023 |

Then User should see the LMS Home page

Here we are passing tables as arguments to step definition instead of using Example keyword. Below is the step definition implementation:

import io.cucumber.datatable.DataTable;

import io.cucumber.java.After;

import io.cucumber.java.Before;

import io.cucumber.java.en.Given;

import io.cucumber.java.en.Then;

import io.cucumber.java.en.When;

import org.junit.Assert;

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import java.util.List;

import java.util.Map;

import java.util.concurrent.TimeUnit;

import static org.hamcrest.CoreMatchers.containsString;

import static org.hamcrest.MatcherAssert.assertThat;

public class DataTableDefinitions {

WebDriver driver;

@Before

public void setup() {

System.setProperty(“webdriver.chrome.driver”,”src/test/resources/Drives/chromedriver.exe”);

driver = new ChromeDriver();

driver.manage().window().maximize();

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

}

@Given(“User is on the Login page”)

public void userOnHomePage() {

driver.get(“https://lms-frontend-phase2.herokuapp.com/login “);

}

@When(“User enters valid credentials”)

public void entersValidCredential(DataTable dataTable) throws InterruptedException{

System.out.println(“Credentials Entered”);

List<String> LoginForm = dataTable.asList();

String userName = LoginForm.get(0);

String passWord = LoginForm.get(1);

driver.findElement(By.name(“Username”)).sendKeys(userName);

driver.findElement(By.name(“Password”)).sendKeys(passWord);

driver.findElement(By.id(“LoginBtn”)).submit();

}

@Then(“User should see the LMS Home page “)

public void successfulLogin() throws InterruptedException {

String Homepage = driver.findElement(By.id(“welcome”)).getText();

System.out.println(“Homepage :” + newPageText);

assertThat(Homepage, containsString(“Welcome”));

}

@After

public void teardown(){

driver.close();

}

}

In this example, a List<List<String>> is used so we can get the data from DataTable. As there is no header in the table, we can get the data from index 0. asLists() method is used which supplies a String class argument and which states asLists() method what is the data type of each element.

· Data Tables with Multiple Test Data using Maps

In this example, let us take multiple entries of Username and Password with Headers.

Feature: Login with valid credentials

Scenario: Successful login with valid credentials

Given User is on the Login Page

When User clicks the Login button after entering valid username and password

| Username | Password |

| Sharon2023 | Welc@2023 |

| Alex123 | Welcome@2022 |

| Shai23 | cAme@2023 |

Then User should see the LMS Home page

In Step definition, only @when method changes rest will be the same as mentioned above.

@When(“User enters valid credentials”)

public void entersValidCredential(DataTable dataTable) throws InterruptedException

{

List<Map<String, String>> user = userTable.asMaps(String.class, String.class);

for (Map<String, String> form : user) {

String userName = form.get(“Username”);

System.out.println(“Username :” + userName);

driver.findElement(By.name(“Username”)).sendKeys(userName);

String passWord = form.get(“Password”);

System.out.println(“Password :” + passWord);

driver.findElement(By.name(“Password”)).sendKeys(passWord);

driver.findElement(By.id(“LoginBtn”)).submit();

}

Here, although a list containing each row is created, Cucumber maps the column heading to each column value. This process is repeated for each subsequent row. To achieve this, asMaps(String, String) method is used which takes two arguments. First argument denotes the data type of the headers (keys) which is String. The second argument also denotes String as the data type column values is String.

Conclusion

In this blog, we saw few examples of how we can add test data to feature files using Data Tables and Scenario Outline. Certainly, the Data Tables can be used to specify the complex data in readable manner. As we learnt, Cucumber automatically converts the Data Tables into particular data structures, which we can iterate to process the data effectively. Thus, the processing time and effort decreases as it iterate over the step definitions instead over the whole specifications.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response