Vertical Data Tables in Cucumber JVM
1. Introduction to Vertical Data Tables
Vertical Data Tables in Cucumber JVM are a clean way to pass one structured business object from a Gherkin feature file into a Step Definition. They are useful when the scenario needs a set of related fields that belong to the same entity, such as a customer, employee, product, order, address, user profile, or login account. Instead of writing many separate Gherkin steps for each field, the scenario can group those fields in a simple key-value table.
A Vertical Data Table is different from a Horizontal Data Table. In a Horizontal Data Table, the first row contains headers and the next rows contain records. In a Vertical Data Table, each row contains one field name and one value. The field names are listed downward in the first column, and the values are listed beside them in the second column. This makes the table easy to read when one object has several properties.
Vertical tables are also different from Scenario Outlines. A Scenario Outline executes the same scenario multiple times using an Examples table. A Vertical Data Table normally executes the scenario once and passes one complete object-like structure to the Step Definition. If you need repeated execution, use Scenario Outline. If you need to pass one structured object, a Vertical Data Table is often a better fit.
When used well, Vertical Data Tables make feature files concise and business-friendly. They reduce repetitive steps, keep related data together, and map naturally into Java maps or POJOs. In larger Cucumber JVM frameworks, they are often converted into domain objects so the rest of the automation code can work with typed values instead of raw strings.
2. What Is a Vertical Data Table?
One Field and One Value per Row
A Vertical Data Table is a Gherkin Data Table where each row represents one field and its corresponding value. The first column contains field names, and the second column contains field values. This format is sometimes called key-value table style because each row behaves like a key-value pair.
Given the following user details
| Username | admin |
| Password | admin123 |
| Role | Admin |
In this example, Username, Password, and Role are field names. The values admin, admin123, and Admin belong to those fields. Together, the table represents one user object.
In simple terms, a Vertical Data Table follows this pattern:
One Field -> One Value per Row
This shape is easy for business readers because it looks like a form or profile summary. Each row has a clear label and a clear value.
3. Why Use a Vertical Data Table?
Use a Vertical Data Table when a scenario needs one object with multiple properties. For example, a customer registration scenario may need first name, last name, email, phone, and city. Writing each value as a separate Gherkin step makes the scenario longer than necessary.
Given the username is "admin"
And the password is "admin123"
And the role is "Admin"
The same information can be grouped as a Vertical Data Table:
Given the following user details
| Username | admin |
| Password | admin123 |
| Role | Admin |
The table version is cleaner because the related information appears together. It also makes the Step Definition easier to maintain because all fields arrive as one DataTable object rather than several separate method calls.
Vertical Data Tables are especially useful when business users prefer key-value style data. A table like this reads like a form. The left side tells what the field is, and the right side tells what value will be used.
4. Vertical Data Table Structure
Field Names in the First Column
The structure of a Vertical Data Table is simple. The first column contains the field or key. The second column contains the value. Unlike a Horizontal Data Table, there is no separate header row. Every row is part of the object.
| Field | Value |
| Username | admin |
| Password | admin123 |
| Role | Admin |
In many Cucumber examples, the first row is not written as Field and Value headers. Instead, every row is directly a key-value pair:
| Username | admin |
| Password | admin123 |
| Role | Admin |
This format maps naturally to a Java Map<String, String>. The first column becomes the map key, and the second column becomes the map value.
5. Horizontal vs Vertical Data Tables
Horizontal and Vertical Data Tables serve different readability needs. A Horizontal Data Table is best when the scenario needs one or more records with the same fields. A Vertical Data Table is best when the scenario needs one object and the fields are easier to read from top to bottom.
// Horizontal
| Username | Password | Role |
| admin | admin123 | Admin |
// Vertical
| Username | admin |
| Password | admin123 |
| Role | Admin |
Horizontal tables are good for lists. Vertical tables are good for one object. If you need to pass three users, horizontal is usually clearer. If you need to pass one customer profile with many fields, vertical is usually clearer.
| Aspect | Vertical Table | Horizontal Table |
|---|---|---|
| Best for | One object | Records or lists |
| Typical Java conversion | Map<String, String> | List<Map<String, String>> |
| Readability strength | Many fields for one entity | Multiple rows with same columns |
6. Execution Flow
When Cucumber executes a step with a Vertical Data Table, it reads the table, creates a DataTable object, and passes it to the Step Definition. The Java method can then convert the table to a map, extract values, and use them in automation code.
Feature File
|
v
Read Vertical Table
|
v
Create DataTable Object
|
v
Convert to Map
|
v
Access Values
|
v
Execute Automation
The scenario still executes once. The table is input to that execution. This is different from Scenario Outline, where every Examples row creates a separate execution.
7. Basic Vertical Data Table Example
A simple login scenario can pass user details as a Vertical Data Table:
Scenario: Login
Given the following user details
| Username | admin |
| Password | admin123 |
| Role | Admin |
The Step Definition receives the DataTable object:
@Given("the following user details")
public void userDetails(DataTable table) {
// Cucumber passes the full table here
}
At this point, the Step Definition has access to the entire table. The next step is to convert it to a Java structure that matches the table shape.
8. Converting a Vertical Data Table to Map
The Recommended Simple Conversion
The most common conversion for a Vertical Data Table is asMap(String.class, String.class). This creates a map where the first column is the key and the second column is the value.
@Given("the following user details")
public void userDetails(DataTable table) {
Map<String, String> user =
table.asMap(String.class, String.class);
}
For the table:
| Username | admin |
| Password | admin123 |
| Role | Admin |
The map contains:
Username -> admin
Password -> admin123
Role -> Admin
This is why Vertical Data Tables are convenient for one object. The table shape directly matches a map shape.
9. Accessing Values from the Map
After converting the table to a map, values can be accessed by field name. The field names used in Java must match the feature file exactly.
Map<String, String> user =
table.asMap(String.class, String.class);
String username = user.get("Username");
String password = user.get("Password");
String role = user.get("Role");
The output values are admin, admin123, and Admin. This approach is readable because the Java code uses the same labels that appear in Gherkin.
However, map access is string-based. If the feature file says User Name and the Java code asks for Username, the lookup fails. Consistent field naming is essential.
10. Complete Example: Employee Details
An employee scenario is a strong example of a Vertical Data Table because one employee has several fields.
Scenario: Employee Details
Given the following employee
| Name | John |
| Department | IT |
| Salary | 80000 |
The Step Definition can convert the table and read each value:
@Given("the following employee")
public void employee(DataTable table) {
Map<String, String> employee =
table.asMap(String.class, String.class);
String name = employee.get("Name");
String department = employee.get("Department");
String salary = employee.get("Salary");
employeeService.createEmployee(name, department, salary);
}
This is clean for a small example. In a larger framework, salary should likely be converted to an int or BigDecimal, and the values should be mapped into an Employee object.
11. Mapping a Vertical Table to a POJO
Stronger Typing for Larger Frameworks
Using a map is convenient, but maps have limitations. Every value is a string, field names are manually typed, and missing keys may not be obvious until runtime. In larger frameworks, it is often better to map table values into a domain object or POJO.
public class Employee {
private String name;
private String department;
private int salary;
public void setName(String name) {
this.name = name;
}
public void setDepartment(String department) {
this.department = department;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
The Step Definition can create the object:
Map<String, String> data =
table.asMap(String.class, String.class);
Employee employee = new Employee();
employee.setName(data.get("Name"));
employee.setDepartment(data.get("Department"));
employee.setSalary(Integer.parseInt(data.get("Salary")));
Once converted, the rest of the framework can use Employee directly. This improves readability and reduces repeated string lookups.
12. Manual Mapping vs Reusable Mappers
Manual mapping is fine for small examples, but it can become repetitive. If many scenarios use customer details, employee details, address details, or product details, repeated map-to-object code should move into reusable mappers or factories.
@Given("the customer details")
public void customerDetails(DataTable table) {
Customer customer = customerTableMapper.toCustomer(table);
customerService.register(customer);
}
This keeps the Step Definition thin. The mapper owns conversion and validation. The service owns business execution. The scenario stays readable. This design is more maintainable than placing conversion logic in every step method.
13. Common Use Cases for Vertical Data Tables
Vertical Data Tables are ideal when one logical object is involved. Common examples include login credentials, customer profiles, employee details, product information, shipping addresses, billing addresses, user preferences, account settings, configuration-like business input, and single order details.
- Login credentials for one user
- Customer registration details
- Employee profile data
- Shipping address fields
- Product information for one product
- User preference settings
- Order summary data
The common pattern is one object with many properties. If the scenario needs many objects, use a Horizontal Data Table instead.
14. Multiple Vertical Tables
A single Vertical Data Table is best for one object. If multiple objects are required, repeating field names vertically can become confusing. For example, listing Username and Password twice in one vertical table makes it unclear where one user ends and another begins.
// Poor
| Username | admin |
| Password | admin123 |
| Username | john |
| Password | pass123 |
If multiple records are needed, a Horizontal Data Table is clearer:
| Username | Password |
| admin | admin123 |
| john | pass123 |
Use the table shape that matches the data shape. One object fits vertical. Multiple records fit horizontal.
15. Vertical Data Table vs Horizontal Data Table
The practical difference between vertical and horizontal tables is how the data is read and what kind of object it represents. Vertical tables usually convert to Map<String, String>. Horizontal tables usually convert to List<Map<String, String>>.
| Aspect | Vertical Data Table | Horizontal Data Table |
|---|---|---|
| Object count | One object | One or more records |
| Conversion | Map<String, String> | List<Map<String, String>> |
| Execution count | One execution | One execution |
| Best for | Key-value data | Record-based data |
16. Vertical Data Table vs Scenario Outline
A Vertical Data Table and a Scenario Outline solve different problems. A Vertical Data Table passes one structured object into one scenario execution. A Scenario Outline runs the same scenario multiple times with different datasets from an Examples table.
| Aspect | Vertical Data Table | Scenario Outline |
|---|---|---|
| Execution count | One execution | Multiple executions |
| Data shape | One object | Multiple datasets |
| Java input | DataTable | Step parameters |
| Best use | Structured input | Data-driven testing |
If the same login scenario should run for Admin, Customer, and Manager as separate tests, use Scenario Outline. If one scenario needs one user's full details, use a Vertical Data Table.
17. Advantages of Vertical Data Tables
Vertical Data Tables are highly readable when one object has several fields. They group related data together, reduce multiple Gherkin steps, and convert easily to maps. They are business-friendly because they look like a labeled form. They also support POJO mapping, which improves maintainability in larger frameworks.
- Highly readable for one object
- Business-friendly key-value format
- Groups related fields together
- Reduces repetitive Gherkin steps
- Easy conversion to Map
- Easy mapping to POJO or domain object
- Good for profile, address, and configuration-like data
18. Limitations of Vertical Data Tables
Vertical Data Tables are not suitable for every case. They usually represent only one object. They are not ideal for multiple records, repeated scenario execution, or large data sets. If the table becomes very long, it can still become hard to maintain.
They also do not provide automatic type safety when converted to a map. Every value begins as a string. Numeric values, dates, booleans, enums, and domain objects require conversion. In larger frameworks, this conversion should be centralized in mapper classes.
19. Common Mistake: Using Vertical Tables for Multiple Objects
A common mistake is trying to represent multiple objects in one vertical table by repeating field names. This is difficult to interpret and easy to break.
// Wrong
| Username | admin |
| Password | admin123 |
| Username | john |
| Password | pass123 |
The correct choice for multiple users is a Horizontal Data Table:
| Username | Password |
| admin | admin123 |
| john | pass123 |
Use vertical for one object. Use horizontal for multiple records.
20. Common Mistake: Missing Field Names
A Vertical Data Table must clearly label every value. A table with only values is not self-descriptive and cannot be converted meaningfully to a map.
// Wrong
| admin |
| admin123 |
// Correct
| Username | admin |
| Password | admin123 |
Every value should have a descriptive key. The key tells both the reader and the automation code what the value represents.
21. Common Mistake: Using Vertical Tables for Data-Driven Testing
Vertical Data Tables do not execute scenarios multiple times. If the same scenario needs to run for Admin, Customer, and Manager, a Vertical Data Table is the wrong mechanism. Use Scenario Outline instead.
Scenario Outline: Login by role
Given the user logs in as "<Role>"
Examples:
| Role |
| Admin |
| Customer |
| Manager |
Use Vertical Data Tables for one structured object. Use Scenario Outline for repeated data-driven execution.
22. Common Mistake: Technical Field Names
Technical or abbreviated field names make feature files harder to understand. A table that uses usr_nm, pwd_val, and rol_cd may make sense to automation code but not to business readers.
// Avoid
| usr_nm | admin |
// Prefer
| Username | admin |
Use business-readable names unless the technical code itself is the business concept being tested. Cucumber feature files should support communication across roles, not only automation execution.
23. Best Practices for Vertical Data Tables
Use Vertical Data Tables for one business object. Convert simple tables to Map<String, String> using asMap(). In larger frameworks, map values into POJOs or domain objects. Use clear business-oriented field names. Keep the table concise and focused on relevant data.
Use Horizontal Data Tables for multiple records. Use Scenario Outlines for repeated executions. Avoid sensitive information, technical configuration, and huge tables in feature files. Keep Step Definitions thin by moving mapping logic into reusable mappers when needed.
- Use vertical tables for one object.
- Use clear key-value field names.
- Convert to Map for simple cases.
- Map to POJOs in larger frameworks.
- Keep data business-readable.
- Use horizontal tables for multiple records.
- Use Scenario Outline for multiple executions.
24. Validating Vertical Data Table Values
Catch Data Problems Early
Vertical Data Tables should be validated before the framework uses their values. Missing fields, empty values, invalid numbers, unsupported statuses, or misspelled keys can cause confusing failures later. Validation belongs in a mapper or helper, not in a large Step Definition.
For example, a customer mapper can check that First Name, Last Name, Email, Phone, and City exist before creating a Customer object. It can also validate email format, parse numeric values, or map role text into an enum. If something is wrong, the mapper can throw a clear error that points to the table data.
@Given("the customer details")
public void customerDetails(DataTable table) {
Customer customer = customerTableMapper.toCustomer(table);
customerService.register(customer);
}
This pattern keeps the step clean and makes table-related failures easier to diagnose.
25. Type Conversion in Vertical Data Tables
From Strings to Meaningful Java Types
When a Vertical Data Table is converted with asMap(String.class, String.class), all values are strings. That is convenient for reading text, but many business fields are not truly strings. Salary may be an integer, invoice amount may be a BigDecimal, active status may be a boolean, and role may be an enum. A mature framework should convert these values into meaningful Java types before passing them deeper into the automation code.
For example, if the table contains Salary = 80000, the Employee object should usually store salary as an int, long, or BigDecimal depending on the business requirement. If the table contains Role = Admin, the framework may convert Admin into Role.ADMIN. If the table contains Active = yes, a mapper may convert that into true or into an AccountStatus enum.
Manual conversion inside every Step Definition creates duplication. A better design is to let a mapper handle conversion consistently. The mapper can trim values, validate required fields, convert numeric values, and throw clear errors when data is invalid. This keeps Step Definitions thin and prevents repeated parsing logic.
public Employee toEmployee(DataTable table) {
Map<String, String> data = table.asMap(String.class, String.class);
Employee employee = new Employee();
employee.setName(required(data, "Name"));
employee.setDepartment(required(data, "Department"));
employee.setSalary(Integer.parseInt(required(data, "Salary")));
return employee;
}
This approach treats the table as business input and the mapper as the translation layer between Gherkin text and Java types.
26. Optional Fields and Default Values
Some Vertical Data Tables contain optional fields. For example, a customer profile may require First Name, Last Name, and Email, but City or Referral Code may be optional. A mapper should define how optional fields are handled. It may use a default value, allow null, or skip setting the property.
Optional fields should be handled deliberately. If the Step Definition blindly calls map.get("City"), it may receive null without explanation. If null is acceptable, that is fine. If the field is required, the mapper should fail early with a clear message. Required and optional rules should not be guessed inside the test flow.
Default values should also be visible through framework conventions. If the table omits Country and the mapper defaults it to USA, the team should know that behavior. Hidden defaults can make scenarios confusing when test results differ from what a reader expects.
A useful rule is to keep mandatory business values in the table and let only stable technical or domain defaults remain hidden. If a value affects the behavior being tested, include it clearly.
27. Maintaining Vertical Data Tables Over Time
Preventing Table Drift
Vertical Data Tables can drift over time as application forms and business rules change. A registration table may start with five fields and later grow to twelve. Some fields may become obsolete. Others may be renamed in the product. If the table is not reviewed, it can become outdated while still appearing valid.
Maintenance should include checking whether each field is still relevant to the scenario. If a field does not affect the behavior being tested, remove it or move it into fixture defaults. If a field name no longer matches business vocabulary, update it. If a table becomes too long, consider whether the scenario is trying to describe too much.
Teams should also watch for duplicate table shapes across feature files. If many scenarios use the same customer details table, a shared mapper and shared naming convention should exist. Without that, small differences in field names can create repeated conversion logic and inconsistent behavior.
A Vertical Data Table should remain readable months after it was written. If future testers cannot understand why a field exists, the table needs cleanup.
28. Real-Time Example: Customer Registration
A customer registration scenario is a natural fit for a Vertical Data Table because one customer has several fields.
Feature: Customer Registration
Scenario: Register Customer
Given the customer details
| First Name | John |
| Last Name | Smith |
| Email | john@test.com |
| Phone | 9999999999 |
| City | Chicago |
The Step Definition can convert the table to a map and populate a Customer object:
@Given("the customer details")
public void customerDetails(DataTable table) {
Map<String, String> customer =
table.asMap(String.class, String.class);
Customer customerObj = new Customer();
customerObj.setFirstName(customer.get("First Name"));
customerObj.setLastName(customer.get("Last Name"));
customerObj.setEmail(customer.get("Email"));
customerObj.setPhone(customer.get("Phone"));
customerObj.setCity(customer.get("City"));
customerService.register(customerObj);
}
This creates one fully populated Customer object from the Vertical Data Table. In a mature framework, the mapping would usually move to a CustomerTableMapper.
29. Real-Time Example: Shipping Address
A shipping address also fits vertical format because it is one object with several labeled fields.
Given the shipping address
| Street | 10 Market Street |
| City | Chicago |
| State | Illinois |
| ZipCode | 60601 |
| Country | USA |
The Step Definition can pass the mapped address to a checkout service or page object. This keeps the scenario compact and avoids five separate address steps.
30. Vertical Data Tables in Large Frameworks
Large frameworks should standardize Vertical Data Table field names and mapping rules. If one feature uses First Name, another uses FirstName, and another uses first_name, mapper code becomes inconsistent. A shared convention helps teams write feature files that are easy to process and easy to read.
Reusable mappers are especially useful. CustomerTableMapper, EmployeeTableMapper, AddressTableMapper, and ProductTableMapper can convert DataTable objects into domain objects. This keeps Step Definitions thin and prevents repeated conversion code.
Large frameworks should also decide how to handle optional fields. A mapper can provide defaults, reject missing required fields, or allow optional values depending on the business rule. These decisions should be centralized instead of scattered across Step Definitions.
31. Vertical Data Tables and Security
Feature files should not contain production secrets, real passwords, tokens, API keys, or sensitive personal information. Vertical Data Tables often resemble forms, so it is easy to accidentally place sensitive values in them. Avoid that pattern.
Use test aliases where possible. For example, the table can say Account Type = PremiumCustomer, and the framework can resolve safe test data from a secure source. This keeps the feature readable without exposing sensitive details.
32. When Not to Use Vertical Data Tables
Do not use a Vertical Data Table when the scenario needs multiple records. Use a Horizontal Data Table instead. Do not use it when the scenario needs repeated execution with multiple datasets. Use Scenario Outline instead. Do not use it for huge objects with dozens of fields if the table becomes hard to read.
The table should make the scenario easier to understand. If the table makes the scenario longer, wider, or more confusing, choose a different structure.
33. Code Review Checklist
Questions Before Committing
Before committing a Vertical Data Table, check whether it represents one object. Confirm that every value has a meaningful field name. Check whether the table is concise and business-readable. Verify that mapping logic is clean and not repeated across many Step Definitions.
- Does the table represent one business object?
- Does every row have a clear field name?
- Are field names business-readable?
- Is the table concise?
- Should the values be mapped to a POJO?
- Would a Horizontal Data Table be better for multiple records?
- Would Scenario Outline be better for repeated executions?
- Is sensitive data excluded?
34. Interview-Ready Summary
Short Explanation for Interviews
A Vertical Data Table is a key-value style Gherkin table where each row represents one field of a single business object. Cucumber passes the table as a DataTable object, and the common conversion is asMap(String.class, String.class). The first column becomes the key, and the second column becomes the value.
Vertical Data Tables are best for one structured object such as a customer, employee, user profile, address, product, or configuration-like business input. In larger frameworks, the map is usually transformed into a POJO for better type safety and maintainability.
- Vertical tables represent one object.
- Each row is one field-value pair.
- asMap() is commonly used for conversion.
- POJO mapping is preferred in larger frameworks.
- Use Horizontal Data Tables for multiple records.
- Use Scenario Outline for repeated executions.
35. Golden Rule
The golden rule is simple: use a Vertical Data Table when your scenario needs one structured business object. Each row should represent one field, making the feature file easy to read, maintain, and map into a domain object.
When Vertical Data Tables are used correctly, they keep Gherkin concise, preserve business readability, and help Cucumber JVM frameworks pass structured data cleanly into Step Definitions.