Examples Table Best Practices in Cucumber JVM
1. Introduction to Examples Table Best Practices
The Examples table is one of the most important parts of a Scenario Outline in Cucumber JVM. It supplies the test data that Cucumber uses to execute the same scenario multiple times. A Scenario Outline provides the reusable scenario structure, while the Examples table provides the variable values that make each execution different. When the table is designed well, the feature file stays readable, business-friendly, and easy to maintain. When the table is poorly designed, the scenario becomes confusing even if the step definitions are technically correct.
Examples tables are often treated as a simple data container, but they are more than that. They are part of the living documentation. A business stakeholder should be able to look at a small Examples table and understand which roles, inputs, amounts, statuses, or expected outcomes are being tested. A tester should be able to see why each row exists. An automation engineer should be able to connect each column to a placeholder and a step definition parameter without guessing.
Poor Examples tables create several problems. They may include duplicate rows, unclear column names, hardcoded technical configuration, sensitive data, too many unrelated columns, or hundreds of rows that make the feature file unreadable. These problems reduce the value of BDD because the feature file stops being a clear description of behavior and becomes a messy spreadsheet embedded inside Gherkin.
The best practice is to keep Examples tables small, meaningful, business-oriented, and focused on variable data. Every row should represent an independent execution. Every column should have a clear business purpose. Data that does not change between rows should come from configuration, setup, fixtures, or services rather than being repeated in the table.
2. Purpose of an Examples Table
Business Test Data for Repeated Behavior
The purpose of an Examples table is to provide the data needed to execute a Scenario Outline multiple times. It should contain only the values that vary between executions. The behavior should remain the same, while the data changes from row to row.
Scenario Outline: Successful Login
Given the user logs in with "<Username>" and "<Password>"
Then the dashboard should be displayed
Examples:
| Username | Password |
| admin | admin123 |
| manager | manager123 |
| customer | customer123 |
In this example, the behavior is successful login. The changing data is username and password. The Examples table is appropriate because each row represents one login execution with a different credential pair.
Think of the Examples table as business test data, not automation configuration. It should describe meaningful data variations for the scenario. It should not store browser names, driver paths, timeouts, environment URLs, internal locators, or framework settings unless those values are genuinely part of the business behavior being tested.
3. Use Meaningful Column Names
Column names should clearly describe the business meaning of the data. A good column name makes the Examples table readable without additional explanation. Names such as Username, Password, Role, Product, Quantity, Amount, Status, ExpectedMessage, and PaymentMethod tell readers what the values represent.
// Good
Examples:
| Username | Password | Role |
| admin | admin123 | Admin |
// Poor
Examples:
| Value1 | Value2 | Value3 |
| admin | admin123 | Admin |
Generic names such as Value1, Value2, Data, Input, and Output make the table harder to understand. They also make step placeholders unclear. A step that says <Value1> does not communicate business meaning. A step that says <Username> is immediately understandable.
Meaningful names also help test reports. When a Scenario Outline row fails, the report often displays example values. Clear column names make failures easier to investigate.
4. Keep Only Variable Data
Do Not Repeat Constants
An Examples table should contain values that change between executions. If a value stays the same for every row, it usually does not belong in the table. Constant values can come from configuration, Background, setup steps, fixtures, or environment settings.
// Good
Scenario Outline: Search Product
When the user searches for "<Product>"
Examples:
| Product |
| Laptop |
| Mobile |
| Camera |
// Poor
Examples:
| Browser | URL | Product |
| Chrome | https://testsite.com | Laptop |
| Chrome | https://testsite.com | Mobile |
| Chrome | https://testsite.com | Camera |
Browser and URL are repeated in every row. They are framework or environment details, not variable business data for the scenario. Including them makes the table wider and less readable without improving test clarity.
This rule is simple but powerful: if a column has the same value in every row, question whether it belongs in the Examples table.
5. Keep Tables Small and Readable
Examples tables work best when they are short enough to understand at a glance. A table with three to ten meaningful rows is usually readable. A table with one hundred rows inside a feature file is usually not. The goal is not to store all possible data combinations inside Gherkin. The goal is to show meaningful business examples.
Examples:
| Product |
| Laptop |
| Mobile |
| Camera |
This table is clear. A business reader can immediately see which products are being covered. If the same table grows to hundreds of rows, it becomes a maintenance burden. Scrolling through huge tables makes the feature file feel like a data file rather than living documentation.
Large data sets should usually move to external sources such as CSV, Excel, JSON, databases, or test data services. Keep feature files focused on behavior and representative data.
6. One Row Equals One Test Case
Each Examples row represents one independent scenario execution. If a table has three rows, Cucumber executes the Scenario Outline three times. This is important for reporting, debugging, and test design.
Examples:
| Username | Password |
| admin | admin123 |
| john | pass123 |
| peter | demo123 |
Cucumber executes login with admin, login with john, and login with peter as separate runs. If the john row fails, the other rows can still pass. This row-level independence is one of the strengths of Scenario Outline.
Because each row is a test case, each row should have a reason to exist. Avoid adding random values just to increase the number of tests. A row should represent a meaningful role, boundary value, input class, business rule, positive case, negative case, or expected outcome.
7. Keep Data Business-Oriented
Use Terms Stakeholders Understand
Examples table data should be understandable to non-technical stakeholders whenever possible. If the business talks about Admin, Customer, and Manager roles, use those values. Avoid internal codes unless the code itself is part of the business rule.
// Business-oriented
Examples:
| Role |
| Admin |
| Customer |
| Manager |
// Less helpful
Examples:
| UserType |
| U001 |
| U002 |
| U003 |
Internal IDs can be useful in automation setup, but they usually make feature files harder to read. If U001 represents Admin, the feature file should usually say Admin and let the automation framework map that value to the correct test data internally.
Business-oriented data makes scenarios easier to review with product owners, business analysts, testers, and developers. It supports the communication purpose of BDD.
8. Avoid Duplicate Rows
Duplicate rows execute the same test repeatedly without adding coverage. They increase execution time and make the table longer without improving confidence.
// Poor
Examples:
| Role |
| Admin |
| Admin |
| Admin |
Each row should represent a unique case or business condition. If Admin appears multiple times, the table should explain why each Admin row is different. For example, Admin with valid password and Admin with invalid password are different cases. Admin repeated three times with the same data is duplication.
Before finalizing an Examples table, scan for repeated rows and remove any that do not add distinct value.
9. Test Positive and Negative Data
Examples tables are useful for covering both positive and negative data when the behavior structure is the same. For a login scenario, one row may represent valid credentials and another may represent an invalid password. The expected result can be included as a column.
Examples:
| Username | Password | ExpectedResult |
| admin | admin123 | Success |
| admin | wrong123 | Failure |
| invalid | admin123 | Failure |
This table improves coverage without duplicating scenario structure. It also makes the expected outcome explicit. However, be careful not to mix unrelated behaviors. Valid and invalid login are still part of login behavior. Login, payment, refund, and profile update do not belong in one Examples table.
10. Group Similar Data with Multiple Examples Sections
Use Group Names for Clarity
Cucumber allows a Scenario Outline to have multiple Examples sections. This is useful when data sets belong to different categories but still use the same scenario structure. Grouping makes the feature file easier to read and reports easier to interpret.
Scenario Outline: Login by role
Given the user logs in as "<Role>"
Then the login result should be "<Result>"
Examples: Valid Roles
| Role | Result |
| Admin | Success |
| Manager | Success |
Examples: Invalid Roles
| Role | Result |
| Guest | Failure |
| Unknown | Failure |
The group names Valid Roles and Invalid Roles explain why the rows are organized separately. This is more readable than mixing all rows together without context.
Use multiple Examples sections when grouping adds meaning. Do not split data randomly. The group name should help the reader understand the purpose of the rows.
11. Keep Data Independent
Each Examples row should be independent. A row should not depend on a previous row running first. Cucumber executes rows as separate scenario executions, and test order should not be required for correctness.
// Good
Examples:
| Product |
| Laptop |
| Mobile |
| Camera |
// Poor
Examples:
| Product |
| First Product |
| Previous Product |
| Next Product |
The poor example suggests that later rows depend on earlier rows. That makes tests fragile. If one row fails or execution order changes, other rows may behave unpredictably. Each row should create, select, or reference data that is valid on its own.
12. Avoid Technical Configuration Data
Examples tables should not contain framework configuration values unless those values are the business subject of the scenario. Browser, driver path, timeout, base URL, execution environment, retry count, and report name usually belong in configuration files or framework settings.
// Avoid
Examples:
| Browser | DriverPath | Timeout |
| Chrome | drivers/chrome.exe | 30 |
This data does not describe the business scenario. It describes how automation runs. Keeping technical settings out of feature files protects business readability and prevents test data from being mixed with execution configuration.
13. Match Column Names Exactly
Placeholders Must Match Headers
Scenario Outline placeholders must match Examples table column names exactly. If a step uses <Role>, the table must contain a column named Role. UserRole is not the same as Role. role is not always treated the same depending on parsing expectations and team conventions. Exact matching prevents substitution errors.
Given the user logs in as "<Role>"
Examples:
| Role |
| Admin |
The following is wrong because the placeholder and header do not match:
Given the user logs in as "<Role>"
Examples:
| UserRole |
| Admin |
Simple naming consistency prevents many avoidable failures.
14. Use Consistent Naming
Choose one naming convention for Examples columns and use it consistently. Title case names such as Username, Password, Role, Product, Quantity, and ExpectedResult are common in feature files. The exact convention matters less than consistency.
// Consistent
Examples:
| Username | Password | Role |
// Inconsistent
Examples:
| User_Name | PASSWORD | roleName |
Inconsistent names make feature files look unpolished and increase the chance of placeholder mistakes. Consistent naming helps teams scan tables quickly and reuse patterns across scenarios.
15. Avoid Sensitive Data
Examples tables should never contain production passwords, API keys, tokens, secrets, personal information, or sensitive customer data. Feature files often live in source control, get shared in reviews, and may appear in reports. Sensitive values should not be exposed there.
Use dummy accounts, test credentials, environment variables, secure secret management, or fixture references. For example, the feature file can say PremiumCustomer or AdminUser while the framework resolves real test credentials from a secure source.
This is not only a best practice for automation. It is a basic security habit. BDD feature files are not secret stores.
16. Do Not Overload a Scenario Outline
Too Many Columns Signal Too Much Behavior
If an Examples table has dozens of unrelated columns, the Scenario Outline may be doing too much. A table with Username, Password, Product, Quantity, Payment, Address, City, Country, Phone, Coupon, ShippingType, TaxRate, and ExpectedMessage may indicate that the scenario is mixing many business behaviors.
// Warning sign
Examples:
| Username | Password | Product | Quantity | Payment | Address | City | Country | Phone | Coupon |
This kind of table is hard to read and hard to maintain. It may be better to split the scenario into smaller focused scenarios, move setup data into fixtures, or use a Data Table for structured input when one execution needs multiple related fields.
A Scenario Outline should remain focused. If the table is difficult to explain, the scenario design probably needs review.
17. Use External Data for Large Datasets
Scenario Outlines work best for small, readable data sets. If the test requires hundreds or thousands of combinations, the feature file is not the right storage location. Large data sets belong in external files or data sources such as CSV, Excel, JSON, databases, APIs, or generated test data.
External data is useful when the data changes frequently, is too large to review in Gherkin, or is generated by another system. The feature file should describe the behavior and maybe a representative example, while the data-driven framework handles bulk coverage.
The decision should be based on readability. If the table helps a human understand the business rule, keep it in the feature file. If the table overwhelms the scenario, move it out.
18. Use Realistic Test Data
Realistic test data makes feature files easier to understand. Values such as John, Mary, Laptop, Mobile, Admin, Premium, and 250.00 are easier to discuss than AAA, BBB, 111, and 222. Realistic data helps business stakeholders connect the scenario to real use cases.
// Better
Examples:
| Customer | Amount |
| John | 250.00 |
| Mary | 500.00 |
// Less helpful
Examples:
| Customer | Amount |
| AAA | 111 |
| BBB | 222 |
Data does not need to be real customer data. It should be realistic dummy data. Avoid sensitive or production information while still keeping examples meaningful.
19. Common Mistake: Duplicate Data
Duplicate data is common when rows are copied and edited quickly. Sometimes the edit is forgotten, leaving repeated rows in the Examples table. This increases execution time without improving coverage.
Examples:
| Role |
| Admin |
| Admin |
Remove duplicate rows unless they intentionally represent different conditions through other columns. Every row should add a distinct case.
20. Common Mistake: Generic Column Names
Generic column names hide meaning. A table with Value1 and Value2 forces the reader to inspect the step text and guess what those values mean. This weakens readability and increases maintenance effort.
// Poor
Examples:
| Value1 | Value2 |
| admin | pass1 |
Use business names instead:
Examples:
| Username | Password |
| admin | pass1 |
21. Common Mistake: Huge Tables
Huge Examples tables are difficult to review and maintain. A 300-row table inside a feature file may technically work, but it makes the feature file poor documentation. It also creates long execution time if every row runs through a UI flow.
When a table grows too large, ask whether the data belongs in an external source. Also ask whether all rows are necessary at the Cucumber layer. Some combinations may be better tested at API or unit level.
22. Common Mistake: Mixed Business Behaviors
An Examples table should not mix unrelated behaviors just because the team wants fewer scenarios. Login, search, payment, logout, refund, and profile update should not usually live in one Scenario Outline. If rows represent different actions, the scenario is no longer a clean template.
Scenario Outline is best when each row follows the same behavior and only the data changes. If behavior changes from row to row, split the scenarios.
23. Common Mistake: Hardcoded Technical Values
Technical values such as Chrome, DriverPath, Timeout, BaseUrl, and ReportName usually do not belong in Examples tables. These values are framework settings. Putting them in Gherkin makes the feature file technical and distracts from business behavior.
Use configuration files, environment variables, CI settings, or framework defaults for technical execution data. Keep Examples tables business-oriented.
24. Best Practices Checklist
Questions Before Finalizing a Table
Before finalizing an Examples table, verify that column names clearly describe business data. Confirm that only variable values are included. Check that every row is independent and meaningful. Remove duplicate rows. Include positive and negative cases where appropriate. Move large data sets to external sources. Exclude sensitive information. Ensure placeholders exactly match column names.
- Do column names describe business meaning?
- Does the table include only variable data?
- Does each row represent one independent execution?
- Is the data realistic and meaningful?
- Have duplicate rows been removed?
- Are positive and negative cases covered when needed?
- Should large data move to an external source?
- Is sensitive information excluded?
- Do placeholders match column names exactly?
25. Real-Time Example: Product Purchase
A product purchase scenario can use an Examples table to cover valid and invalid purchases while keeping the behavior consistent.
Feature: Product Purchase
Scenario Outline: Purchase Product
Given the customer "<Customer>" purchases "<Product>"
When the quantity is <Quantity>
Then the total amount should be <Amount>
Examples: Valid Purchases
| Customer | Product | Quantity | Amount |
| John | Laptop | 1 | 1000 |
| Mary | Mobile | 2 | 1200 |
| David | Camera | 3 | 1500 |
Examples: Invalid Purchases
| Customer | Product | Quantity | Amount |
| John | Laptop | 0 | 0 |
| Mary | Mobile | -1 | 0 |
This design uses meaningful column names, separates valid and invalid cases, keeps the behavior unchanged, and changes only the test data. It is readable for both business and technical audiences.
26. Examples Table and Step Definitions
The Examples table works with Scenario Outline placeholders, and the final substituted step works with Step Definitions. The table column may be Product, the scenario placeholder may be <Product>, and the Step Definition may capture the substituted value with {string}.
@Given("the customer {string} purchases {string}")
public void customerPurchases(String customer, String product) {
purchaseService.preparePurchase(customer, product);
}
@When("the quantity is {int}")
public void quantityIs(int quantity) {
purchaseService.setQuantity(quantity);
}
This separation is important. Examples table headers are not Java variables. They are Gherkin placeholders that are replaced before Cucumber Expression matching occurs.
27. Examples Table and Reporting
Each Examples row appears as a separate execution in test reports. Clear column names and meaningful values make reports easier to interpret. When a row fails, the data attached to that row should help the tester understand the failure quickly.
If the report shows Customer = Mary, Product = Mobile, Quantity = -1, and Amount = 0, the failure context is clear. If the report shows Value1 = BBB and Value2 = 222, the failure requires more investigation. Good Examples table design improves reporting quality.
28. Examples Table in Large Frameworks
Balancing Readability and Coverage
Large frameworks need a clear data strategy. Examples tables are excellent for small business-readable data sets, but they should not become the only data-driven mechanism. Some tests need representative examples in Gherkin. Other tests need large generated data sets, environment-specific data, or external data maintained by another system.
A good framework uses Examples tables where they improve communication and external data where volume or volatility would damage readability. This balance keeps feature files useful as documentation while still supporting broad automated coverage.
Teams should also review Examples tables periodically. Business rules change, roles are added, statuses are retired, and product names evolve. Old rows can become misleading even if they still execute. Maintaining table data is part of maintaining the test suite.
29. Maintaining Examples Tables Over Time
Keeping Data Useful After the First Version
Examples tables often start clean and become messy slowly. A scenario begins with three useful rows, then another row is added for a new role, another for a bug fix, another for a region-specific behavior, and another for a temporary production issue. After several releases, the table may contain old values that nobody understands. The scenario still runs, but the table no longer communicates clearly.
To avoid this, Examples tables should be maintained like code. Each row should have a reason to exist. If a row covers a boundary condition, invalid input, permission rule, or regression defect, the value should make that purpose visible. When rows become obsolete, remove them. When rows duplicate other rows, consolidate them. When a table becomes too wide or too long, review whether the scenario is doing too much.
It is also useful to keep expected results explicit when positive and negative data are mixed. A table that includes both valid and invalid login attempts should usually include a column such as ExpectedResult or ExpectedMessage. This prevents the reader from guessing which rows are supposed to pass and which are supposed to fail. Clear expected result columns also make Step Definitions and reports easier to understand.
Teams should review Examples tables during pull requests, not only Java code. A poorly designed table can create the same maintenance problems as poorly designed code. Reviewers should ask whether the table is readable, whether each row is independent, whether business terminology is consistent, and whether any data should move to configuration or external files.
Good maintenance keeps Examples tables valuable as living documentation. The table should continue to explain the business rule months after it was first written. If the team cannot explain why a row exists, that row should be questioned.
30. Examples Tables and Test Coverage Strategy
Choosing Rows with Purpose
An Examples table is not a place to add random data. It should represent a deliberate coverage strategy. Each row should cover a meaningful condition, such as a happy path, negative path, boundary value, equivalence class, role variation, payment method, customer segment, or expected business outcome. This makes the table smaller and stronger.
For example, a password validation table does not need every possible password. It needs representative values: a valid password, an empty password, a password that is too short, a password without a number, a password without an uppercase character, and perhaps a password with unsupported symbols. These rows explain the validation rule better than dozens of arbitrary values.
Examples tables can also support regression testing. If a defect was fixed for a specific input, a row can be added to capture that case. But the row should still be understandable. If the defect row uses unusual data, add clear column names or expected result values so future readers know what behavior is being protected.
Coverage should also be balanced across test levels. If a rule has hundreds of numeric combinations, not all of them belong in a Cucumber Examples table. Many combinations may be better tested through unit tests, API tests, or generated data-driven checks. Use Cucumber examples for business-readable coverage and use lower-level tests for exhaustive combinations.
The best Examples tables are intentionally small. They do not cover everything. They cover the important cases that communicate the rule and provide confidence at the BDD layer.
31. Examples Tables and Automation Stability
Examples table design can affect automation stability. If rows depend on fragile data, shared accounts, previous executions, or environment-specific state, the Scenario Outline may become flaky. Each row should use reliable data that can be created, reset, or resolved independently.
For user accounts, prefer role-based test fixtures or generated test users instead of hardcoded shared accounts when possible. For products, use stable test catalog items or create products through setup services. For amounts and statuses, choose values that are valid for the current business rules. Avoid rows that depend on production-like data changing outside the test team's control.
Independence matters especially when scenarios run in parallel. If two Examples rows use the same account and both modify its state, they may interfere with each other. A table that looks fine in sequential execution may fail in parallel execution. Design table data with isolation in mind.
Stable Examples tables make Scenario Outlines easier to trust. When a row fails, the team should suspect a real behavior issue or a clear automation issue, not hidden dependency between rows.
32. When Not to Use an Examples Table
Do not use an Examples table when there is only one simple case and no expected need for more data. A normal Scenario may be clearer. Do not use an Examples table to combine unrelated behaviors. Do not use it to store technical configuration. Do not use it to hold huge data sets that nobody can review meaningfully.
Scenario Outline and Examples tables are tools for repeated behavior with different data. If that condition is not true, another structure is probably better.
33. Interview-Ready Summary
Short Explanation for Interviews
The Examples table supplies data for a Scenario Outline and allows the same scenario to execute multiple times with different input values. Each row represents one independent execution. Good Examples tables use meaningful column names, include only variable business data, avoid duplicates, and remain small enough to read.
Related data can be grouped using multiple Examples sections. Sensitive data and technical configuration should not be stored in feature files. Very large or frequently changing data sets should move to external files or data sources.
- Examples tables drive Scenario Outline execution.
- One row equals one independent test execution.
- Column names should describe business meaning.
- Only variable business data belongs in the table.
- Large datasets should move outside feature files.
34. Golden Rules
The golden rules are simple. One row should represent one independent test execution. Store only business data in the Examples table. Use meaningful column names. Keep tables small, readable, and maintainable. Move large data sets to external sources when they outgrow the feature file.
When Examples tables are designed well, Scenario Outlines become clear, powerful, and maintainable. They help Cucumber JVM support data-driven testing without sacrificing the readability that makes BDD valuable.