DEV Community

Cover image for Java + Cucumber + Generator: Automating Step Definition Creation
uttesh
uttesh

Posted on

Java + Cucumber + Generator: Automating Step Definition Creation

This is an advanced automation approach for generating step definitions in Java using Cucumber. Let's generate step classes using the Mustache templates and Gradle tasks to simplify and streamline the creation of step definition classes for your Cucumber feature files. This approach is for developers who want to eliminate boilerplate code and focus on building robust test automation frameworks.

Introduction to Cucumber and Java

Cucumber is a popular testing tool that bridges the gap between technical and non-technical teams. It uses Behavior-Driven Development (BDD) principles to define application behaviour in plain English. However, writing step definition classes for each feature file can become repetitive and time-consuming.

Why Automate Step Definitions?

Image description

Manual creation of step definitions:

  • Requires developers to repetitively translate feature file scenarios into methods.
  • Can lead to errors or inconsistencies in naming and structure.
  • Slows down the development process for large-scale projects.

Automating this process:

  • Saves time by generating classes dynamically.
  • Ensures consistency across all step definitions.
  • Makes the framework scalable and maintainable.

Step-by-Step Explanation

Step 1: Parse the Feature File

The first step involves reading the feature file and extracting scenarios and steps. Each scenario is broken down into:

  • Scenario title
  • Steps (Given, When, Then, etc.)
private static List<ScenarioData> parseFeatureFile(String featureFilePath) throws IOException {
    List<ScenarioData> scenarios = new ArrayList<>();
    List<String> currentSteps = new ArrayList<>();
    String currentScenario = null;

    try (BufferedReader reader = new BufferedReader(new FileReader(featureFilePath))) {
        String line;
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (line.startsWith("Scenario:")) {
                if (currentScenario != null) {
                    scenarios.add(new ScenarioData(currentScenario, new ArrayList<>(currentSteps)));
                    currentSteps.clear();
                }
                currentScenario = line.substring("Scenario:".length()).trim();
            } else if (line.matches("^(Given|When|Then|And|But) .+")) {
                currentSteps.add(line);
            }
        }
        if (currentScenario != null) {
            scenarios.add(new ScenarioData(currentScenario, currentSteps));
        }
    }
    return scenarios;
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Use Mustache Template for Class Generation

With scenarios extracted, each scenario is used to generate a corresponding Java class. Mustache templates define how each class and its methods are structured.

Template Example (StepDefinition.mustache):

package {{packageName}};

import io.cucumber.java.en.*;

public class {{className}} {

{{#methods}}
    @{{stepType}}("^{{stepText}}$")
    public void {{methodName}}() {
        // TODO: Implement step: {{stepText}}
    }
{{/methods}}
}

Enter fullscreen mode Exit fullscreen mode

Step 3: Generate Java Classes

Each scenario is passed through the Mustache template, and the output is saved as a .java file in the designated directory.

Code Snippet:

private static void generateStepDefinition(ScenarioData scenario, String outputFilePath, String className) throws IOException {
    List<Map<String, String>> methods = extractStepDefinitions(scenario.getSteps());
    Map<String, Object> templateData = new HashMap<>();
    templateData.put("packageName", "com.example.steps");
    templateData.put("className", className);
    templateData.put("methods", methods);

    String templateFile = "src/main/resources/templates/StepDefinition.mustache";
    renderTemplate(templateFile, outputFilePath, templateData);
}

Enter fullscreen mode Exit fullscreen mode

Step 4: Automate the Process with Gradle

Integrate the generator into your Gradle build process to automate step definition creation. A Gradle task is defined to invoke the generator with feature file paths.

Gradle Task:

tasks.register("generateStepDefinitions", JavaExec) {
    group = "custom"
    description = "Generates step definition classes from feature files."
    mainClass = "com.example.CucumberStepGenerator"
    classpath = sourceSets.main.runtimeClasspath
    args = [
        "src/test/resources/features/sample.feature",
        "src/test/java/com/example/steps"
    ]
}

Enter fullscreen mode Exit fullscreen mode

Benefits of Using a Generator

  • Time-Saving: Reduces manual effort in creating step definitions.
  • Consistency: Ensures uniform formatting and naming conventions.
  • Scalability: Easily adapts to large projects with multiple feature files.
  • Customizability: Modify templates to match your specific requirements.

Source Code Github: https://github.com/uttesh/cucumber-step-generator

Image description

Conclusion
By combining Cucumber, Java, and Mustache templates, you can revolutionize the way step definitions are generated in your projects. This approach is a game-changer for teams working with BDD frameworks, enabling them to focus on test logic rather than repetitive setup tasks.

Stay tuned for more advanced topics on test automation!

Top comments (0)