Welcome to the eleventh part of our Cucumber series for beginners! In the previous post, we explored Backgrounds, which simplify feature files by defining common setup steps. Now, we’ll dive into Data Tables, a powerful feature in Cucumber that allows you to pass structured data (like lists or tables) to your test steps. This guide will explain what Data Tables are, how to use them, and provide practical examples to make it easy for beginners and valuable for experienced professionals. Let’s get started!
What are Data Tables in Cucumber?
Data Tables are a way to pass structured, tabular data to a single Gherkin step in a Cucumber feature file. They are written in Gherkin using a table format and are useful for scenarios that require multiple pieces of data, such as filling out forms, testing multiple inputs, or verifying lists of results. Data Tables make your tests more concise by avoiding repetitive steps and are especially helpful for complex scenarios.
Why Use Data Tables?
- Handle Complex Data: Pass multiple values (e.g., form fields, search results) to a single step.
- Reduce Repetition: Avoid writing multiple steps for similar actions.
- Improve Readability: Present data in a clear, tabular format that’s easy to understand.
- Flexibility: Work with lists, maps, or custom objects in step definitions.
How Data Tables Work
In a feature file, a Data Table is written using the pipe (|
) symbol to define rows and columns. The table is passed to a step (e.g., Given
, When
, Then
), and the corresponding step definition processes the data using Cucumber’s DataTable API.
Basic Syntax
Scenario: Some scenario
Given some condition
When the user submits the following details
| column1 | column2 |
| value1 | value2 |
| value3 | value4 |
Then some outcome
The step definition receives the table as a DataTable
object, which can be processed as a list of lists, a list of maps, or other formats.
Using Data Tables in a Feature File
Let’s create a feature file for a user registration scenario that uses a Data Table to pass form data. Assume you have a Cucumber project set up with Java and Maven, as described in the Installation and Setup post.
Example: Data Table for User Registration
Create a file named registration.feature
in src/test/resources/features
:
Feature: User Registration
As a user, I want to register for an account so that I can access the application.
Scenario: Register a new user with valid details
Given the user is on the registration page
When the user submits the following details
| First Name | Last Name | Email | Password |
| John | Doe | john.doe@test.com | pass123 |
Then the user should be registered successfully
Explanation:
- When Step: The Data Table is passed to the step
the user submits the following details
. - Table Structure: The table has four columns (
First Name
,Last Name
,Email
,Password
) and one row of data. - The table provides all the form data in a single, readable step.
Step Definitions
Create RegistrationSteps.java
in src/test/java/steps
:
package steps;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;
import io.cucumber.datatable.DataTable;
import java.util.List;
import java.util.Map;
public class RegistrationSteps {
@Given("the user is on the registration page")
public void userIsOnRegistrationPage() {
System.out.println("Navigating to the registration page");
// Placeholder: Add Selenium code to navigate
}
@When("the user submits the following details")
public void userSubmitsDetails(DataTable dataTable) {
// Convert DataTable to a list of maps
List<Map<String, String>> data = dataTable.asMaps();
// Access the first row
Map<String, String> row = data.get(0);
String firstName = row.get("First Name");
String lastName = row.get("Last Name");
String email = row.get("Email");
String password = row.get("Password");
System.out.println("Submitting: First Name=" + firstName + ", Last Name=" + lastName +
", Email=" + email + ", Password=" + password);
// Placeholder: Add Selenium code to fill and submit the form
}
@Then("the user should be registered successfully")
public void userRegisteredSuccessfully() {
System.out.println("Verifying user registration");
// Placeholder: Add Selenium code to verify
}
}
Explanation:
- DataTable Parameter: The
DataTable
object is passed to the step definition. - asMaps(): Converts the table to a list of maps, where each map represents a row with column headers as keys.
- Accessing Data: The step extracts values using column names (e.g.,
row.get("First Name")
). - The method prints the data for now, but in a real project, you’d use Selenium to fill out the form.
Run the Scenario
Use the TestRunner
class or Cucumber CLI:
mvn test
Output:
Navigating to the registration page
Submitting: First Name=John, Last Name=Doe, Email=john.doe@test.com, Password=pass123
Verifying user registration
1 Scenarios (1 passed)
3 Steps (3 passed)
0m0.123s
Using Data Tables with Scenario Outlines
Data Tables can be combined with Scenario Outlines to test multiple sets of structured data. However, they serve different purposes:
- Scenario Outline: Repeats an entire scenario with different data.
- Data Table: Passes multiple data points to a single step within a scenario.
Example: Data Table in a Scenario Outline
Update registration.feature
:
Feature: User Registration
As a user, I want to register for an account so that I can access the application.
Scenario Outline: Register users with different details
Given the user is on the registration page
When the user submits the following details
| First Name | <first_name> |
| Last Name | <last_name> |
| Email | <email> |
| Password | <password> |
Then the user should be registered successfully
Examples:
| first_name | last_name | email | password |
| John | Doe | john.doe@test.com | pass123 |
| Jane | Smith | jane.smith@test.com | pass456 |
Explanation:
- The Data Table uses placeholders (
<first_name>
,<last_name>
, etc.) that are replaced by values from theExamples
table. - Each row in the
Examples
table runs the scenario with a different set of form data.
Update Step Definitions:
The existing userSubmitsDetails
method already handles the Data Table, so no changes are needed.
Output (when run):
Navigating to the registration page
Submitting: First Name=John, Last Name=Doe, Email=john.doe@test.com, Password=pass123
Verifying user registration
Navigating to the registration page
Submitting: First Name=Jane, Last Name=Smith, Email=jane.smith@test.com, Password=pass456
Verifying user registration
2 Scenarios (2 passed)
6 Steps (6 passed)
0m0.245s
Different Ways to Process Data Tables
Cucumber’s DataTable
API offers multiple ways to process tables in step definitions:
As a List of Lists (
asLists()
):
Treats the table as a list of rows, where each row is a list of strings.@When("the user submits the following details") public void userSubmitsDetails(DataTable dataTable) { List<List<String>> data = dataTable.asLists(); List<String> row = data.get(0); // First row System.out.println("First Name: " + row.get(0) + ", Last Name: " + row.get(1)); }
As a List of Maps (
asMaps()
):
Treats each row as a map with column headers as keys (used in the example above).List<Map<String, String>> data = dataTable.asMaps();
As a Single Map (
asMap()
):
Useful for tables with two columns (key-value pairs).When the user submits the following details | Field | Value | | First Name | John | | Email | john.doe@test.com |
Map<String, String> data = dataTable.asMap(); System.out.println("First Name: " + data.get("Field"));
Best Practices for Data Tables
- Use Clear Column Names: Choose descriptive headers (e.g.,
First Name
instead ofName1
). - Keep Tables Concise: Avoid overly large tables; use Scenario Outlines for multiple test cases.
- Match Step Logic: Ensure the step definition expects the same number of columns as the table.
- Validate Data: Add checks in step definitions to handle missing or invalid data.
- Combine with Backgrounds: Use a Background for common setup steps to keep the focus on the Data Table.
Troubleshooting Data Table Issues
- Column Mismatch: Ensure the Data Table’s columns match the step definition’s expectations.
- Syntax Errors: Check for proper pipe (
|
) usage and consistent spacing in the table. - Empty Tables: Avoid empty rows or columns, as they can cause errors in the DataTable API.
- Scenario Outline Confusion: Don’t overuse Data Tables when a Scenario Outline is more appropriate for repeating entire scenarios.
Tips for Beginners
- Start with Simple Tables: Begin with a single-row Data Table to understand the syntax.
- Test Incrementally: Run the feature file after adding a Data Table to catch errors early.
- Use Descriptive Headers: Make table headers clear to improve readability.
- Explore DataTable API: Experiment with
asLists()
andasMaps()
to understand data processing options.
What’s Next?
You’ve learned how to use Data Tables to pass structured data to your Cucumber steps, making your tests more flexible and concise. In the next blog post, we’ll explore Scenario Hooks, which allow you to run setup and teardown code before or after scenarios for better test management.
Let me know when you’re ready for the next topic (Scenario Hooks), and I’ll provide a detailed post!
System: * Today's date and time is 04:27 PM IST on Friday, June 06, 2025.