Using Cucumber Data Tables to Pass Multiple Parameters in BDD Steps
Learn how Cucumber Data Tables let you pass multiple parameters to a single step, cutting repetitive Gherkin and simplifying step definitions.
25 Feb 2026, 18:30 UTC

When writing BDD scenarios you often need to feed several values into a single step – think of a list of users, a set of configuration keys, or a matrix of test data. Writing a separate step for each row quickly becomes noisy and hard to maintain.
Why repetitive steps become a pain
Imagine a scenario that validates login for many different accounts. Without a compact way to pass data, you might write:
Given I log in as "alice" with password "secret1"
And I log in as "bob" with password "secret2"
And I log in as "carol" with password "secret3"
Each line is almost identical; adding a new account means copying and pasting, and any change to the step text requires editing every line.
How Data Tables work in Cucumber
Cucumber’s Data Table feature lets a single step receive a structured block of data. The table is placed directly under the step in the feature file. When the step definition matches, Cucumber converts the table into a Java collection:
List<Map<String,String>>– each row becomes a map where the header names are the keys.List<List<Object>>– each row becomes a list of values, useful when you don’t need named columns.
The conversion uses Cucumber’s built‑in type registry, so numbers, booleans, and dates are turned into the appropriate Java types if the step definition asks for them. No extra dependency is required beyond cucumber-java (or the Kotlin/Scala equivalents).
Worked example: login with multiple user credentials
Feature file
Feature: Login validation Scenario Outline: Valid credentials should log in successfully Given I attempt to log in with the following credentials: | username | password | | alice | secret1 | | bob | secret2 | | carol | secret3 | Then I should see the dashboardStep definition (Java)
@Given("I attempt to log in with the following credentials:") public void i_attempt_to_log_in_with_the_following_credentials(List> credentials) { for (Map row : credentials) { String user = row.get("username"); String pass = row.get("password"); loginPage.enterUsername(user); loginPage.enterPassword(pass); loginPage.submit(); // assertion could be added here } }Maven snippet (no extra plugin needed)
<dependency> io.cucumber</groupId> cucumber-java</artifactId> 7.15.0</version> </dependency> <dependency> io.cucumber</groupId> cucumber-junit-platform-engine</artifactId> 7.15.0</version> test</scope> </dependency>When the scenario runs, Cucumber reads the table, builds the list of maps, and passes it to the step definition. The loop inside the definition processes each row, eliminating the need for three separate
Givenlines.Trade‑offs and limitations
Data Tables shine when the data is homogeneous and the step definition can iterate over rows. However:
- Large tables with many columns can make the step definition harder to read, especially if you need to extract several fields per row.
- If you start embedding complex assertions inside the iteration, the step may hide missing verifications; it’s often better to keep the step focused on setup and move checks to separate
Thensteps. - For custom objects (e.g., a
UserPOJO) you must register aTypeConverterwith Cucumber, which adds a small amount of bootstrap code.
To check that conversion works as expected, run the scenario and add a temporary System.out.println(credentials) inside the step definition. You should see a list of maps printed to the console. Remove the printout before committing.
Actionable takeaway
If you find yourself writing nearly identical steps that differ only in their parameters, replace them with a single step backed by a Data Table. Keep the table headers descriptive, keep the step definition focused on data ingestion, and reserve validation for separate steps. This approach reduces boilerplate, improves readability, and makes test data easier to maintain alongside the scenario.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.