Cucumber - DataTables

Cucumber - DataTables

Cucumber DataTables allow you to handle tabular data in your feature files efficiently. DataTables are especially useful when working with multiple rows or columns of data, enabling seamless data transfer from feature files to step definitions. They make tests more readable, reusable, and maintainable.

What Are DataTables?

DataTables in Cucumber let you pass structured data into your step definitions. This data can represent various inputs, such as login credentials, user details, or configuration settings.

Example: Using DataTables

Below is a complete example demonstrating the use of DataTables for testing a user registration feature.

Feature File (RegistrationFeature.feature)

                  
                    Feature: User Registration
                      Test the registration functionality with multiple users.
              
                      Scenario: Register new users with valid details
                        Given the following users register:
                          | username  | email              | password    |
                          | user1     | user1@example.com  | pass123     |
                          | user2     | user2@example.com  | password456 |
                          | user3     | user3@example.com  | pass789     |
                        Then each user should receive a confirmation email
                  
                

Step Definitions File (RegistrationSteps.java)

                  
                    package com.example.tests;
              
                    import io.cucumber.java.en.Given;
                    import io.cucumber.java.en.Then;
                    import io.cucumber.datatable.DataTable;
              
                    import java.util.List;
                    import java.util.Map;
              
                    public class RegistrationSteps {
              
                        @Given("the following users register:")
                        public void usersRegister(DataTable dataTable) {
                            List<Map<String, String>> users = dataTable.asMaps();
                            for (Map<String, String> user : users) {
                                System.out.println("Registering user:");
                                System.out.println("Username: " + user.get("username"));
                                System.out.println("Email: " + user.get("email"));
                                System.out.println("Password: " + user.get("password"));
                                // Code to register the user (e.g., API call, database insert)
                            }
                        }
              
                        @Then("each user should receive a confirmation email")
                        public void verifyConfirmationEmails() {
                            System.out.println("Verifying confirmation emails for all registered users...");
                            // Code to verify emails have been sent
                        }
                    }
                  
                

Test Runner File (TestRunner.java)

                  
                    package com.example.tests;
              
                    import io.cucumber.testng.AbstractTestNGCucumberTests;
                    import io.cucumber.testng.CucumberOptions;
              
                    @CucumberOptions(
                        features = "src/test/resources/features",
                        glue = "com.example.tests"
                    )
                    public class TestRunner extends AbstractTestNGCucumberTests {
                        // No additional code required; Cucumber handles execution
                    }
                  
                

Real-World Use Cases

  • Login Testing: Test multiple login credentials using a DataTable for username and password combinations.
  • API Testing: Send various JSON payloads by transforming DataTable inputs into API request bodies.
  • Database Verification: Pass expected database records in a DataTable and verify them against actual results.
  • E-commerce Testing: Test cart functionality by adding products with attributes like name, quantity, and price from a DataTable.

Advanced Use: Custom Object Mapping

You can map DataTables directly to custom Java objects for better readability and maintainability. Here's an example:

Feature File

                  
                    Scenario: Register new users with details mapped to custom objects
                      Given the following user details:
                        | username | email             | age |
                        | john     | john@example.com  | 25  |
                        | alice    | alice@example.com | 30  |
                  
                

Step Definitions File

                  
                    package com.example.tests;
              
                    import io.cucumber.java.en.Given;
                    import io.cucumber.datatable.DataTable;
              
                    import java.util.List;
              
                    public class AdvancedRegistrationSteps {
              
                        public static class User {
                            private String username;
                            private String email;
                            private int age;
              
                            public User(String username, String email, int age) {
                                this.username = username;
                                this.email = email;
                                this.age = age;
                            }
              
                            @Override
                            public String toString() {
                                return "User{username='" + username + "', email='" + email + "', age=" + age + "}";
                            }
                        }
              
                        @Given("the following user details:")
                        public void userDetails(DataTable dataTable) {
                            List<User> users = dataTable.asList(User.class);
                            for (User user : users) {
                                System.out.println("Registering user: " + user);
                                // Code to register the user
                            }
                        }
                    }
                  
                

Benefits of Using DataTables

  • Makes tests more readable by separating data from logic.
  • Enables testing with large, structured datasets.
  • Supports mapping to custom objects for improved clarity.
  • Facilitates testing complex workflows with tabular data.