Cucumber Reporting — Allure, ExtentReports, Cucumber HTML

9 min read

Tests only earn their keep if failures get noticed. A green build that silently hides a flaky test suite is worse than no test suite at all. Good reporting turns raw pass/fail data into actionable information — which scenarios failed, what the response body was, which screenshot shows the broken UI, and how the failure rate trends over time.

Cucumber supports multiple reporting layers simultaneously. This lesson covers the full range: from the built-in HTML report to the enterprise-grade Allure dashboard.

Built-in Cucumber reports

Cucumber's plugin system is configured in the runner class:

@ConfigurationParameter(
    key = PLUGIN_PROPERTY_NAME,
    value = "pretty, " +
            "html:target/cucumber-reports/report.html, " +
            "json:target/cucumber-reports/report.json, " +
            "junit:target/cucumber-reports/report.xml"
)
  • pretty — coloured step-by-step output in the console with pass/fail indicators
  • html:path — a standalone HTML file viewable in any browser; includes feature file names, scenario names, step statuses, embedded screenshots
  • json:path — machine-readable JSON; the input format for third-party reporting tools
  • junit:path — JUnit XML; consumed by CI servers (Jenkins, GitHub Actions) for test result trends

All four can be active simultaneously. The JSON report is the most useful output — every other tool reads it.

cucumber-reporting: rich HTML from JSON

The masterthought cucumber-reporting library takes the JSON output and produces a rich HTML dashboard with charts, trend tracking, and pass/fail breakdowns by feature:

<plugin>
    <groupId>net.masterthought</groupId>
    <artifactId>maven-cucumber-reporting</artifactId>
    <version>5.8.1</version>
    <executions>
        <execution>
            <id>generate-reports</id>
            <phase>verify</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/cucumber-html-reports</outputDirectory>
                <inputDirectory>${project.build.directory}/cucumber-reports</inputDirectory>
                <jsonFiles>
                    <param>**/report.json</param>
                </jsonFiles>
                <projectName>BDD Test Suite</projectName>
                <buildNumber>${env.BUILD_NUMBER}</buildNumber>
            </configuration>
        </execution>
    </executions>
</plugin>

Run mvn verify to generate the report after tests complete. The output is a multi-page HTML site at target/cucumber-html-reports/overview-features.html. The overview shows pass/fail percentages per feature. The feature detail page shows each scenario and step.

Allure: the enterprise reporting tool

Allure is the most feature-rich option: interactive reports with filtering, history tracking, environment info, and support for attachments. The Cucumber 7 integration requires one dependency:

<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-cucumber7-jvm</artifactId>
    <version>2.25.0</version>
    <scope>test</scope>
</dependency>

Register it as a Cucumber plugin:

@ConfigurationParameter(
    key = PLUGIN_PROPERTY_NAME,
    value = "pretty, " +
            "html:target/cucumber-reports/report.html, " +
            "io.qameta.allure.cucumber7jvm.AllureCucumber7Jvm"
)

Allure writes JSON results to target/allure-results/ during the test run. Generate the HTML report:

allure serve target/allure-results        # opens browser immediately
allure generate target/allure-results -o target/allure-report  # writes to disk

Allure reads Gherkin structure natively — features appear as test suites, scenarios as test cases, steps with their status. Screenshots attached via scenario.attach(...) appear in the test detail view.

ExtentReports is widely used in the Selenium world and has a Cucumber adapter:

<dependency>
    <groupId>tech.grasshopper</groupId>
    <artifactId>extentreports-cucumber7-adapter</artifactId>
    <version>1.14.0</version>
    <scope>test</scope>
</dependency>

Configuration file src/test/resources/extent.properties:

extent.reporter.spark.start=true
extent.reporter.spark.out=target/extent-reports/index.html

Plugin registration:

@ConfigurationParameter(
    key = PLUGIN_PROPERTY_NAME,
    value = "pretty, " +
            "html:target/cucumber-reports/report.html, " +
            "com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:"
)

Note the trailing colon on the ExtentReports plugin class name — it is required.

Attaching screenshots in reports

Screenshots attached via Scenario.attach() are embedded automatically in Allure, the Cucumber HTML report, and ExtentReports. The key is always in the @After hook:

@After
public void afterScenario(Scenario scenario) {
    WebDriver driver = context.getDriver();
    if (scenario.isFailed() && driver != null) {
        byte[] screenshot = ((TakesScreenshot) driver)
            .getScreenshotAs(OutputType.BYTES);
        scenario.attach(screenshot, "image/png", scenario.getName());
    }
    context.quitDriver();
}

For Allure, you can also attach the page source for deep debugging:

if (scenario.isFailed() && driver != null) {
    // Screenshot
    byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
    scenario.attach(screenshot, "image/png", "screenshot");
 
    // Page source
    String pageSource = driver.getPageSource();
    scenario.attach(pageSource.getBytes(), "text/html", "page-source");
}

Choosing a reporter

Configuring CI to publish reports

GitHub Actions example — publish Allure reports to GitHub Pages:

- name: Run tests
  run: mvn test -Dcucumber.filter.tags="@regression" -Dheadless=true
 
- name: Generate Allure Report
  if: always()
  run: allure generate target/allure-results -o target/allure-report --clean
 
- name: Publish to GitHub Pages
  if: always()
  uses: peaceiris/actions-gh-pages@v3
  with:
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: target/allure-report

if: always() ensures the report is generated and published even when tests fail — which is exactly when you need it most. The JUnit XML report (junit:target/...) published alongside is consumed by GitHub's native test result display.

⚠️ Common mistakes

  • Not generating the Allure report before opening it. allure serve streams results from target/allure-results/ — if you open target/allure-results/ directly in a browser, you see raw JSON files. Always run allure serve or allure generate first.
  • Missing the trailing colon on the ExtentReports plugin string. com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter: — the colon is part of the plugin configuration syntax for adapters. Without it, ExtentReports silently doesn't activate.
  • testFailureIgnore absent in Surefire when tests fail. By default, Maven stops the build on test failure before the verify phase runs, so maven-cucumber-reporting never executes. Add <testFailureIgnore>true</testFailureIgnore> to Surefire in CI pipelines where you want reports even from failing builds.
  • Screenshot MIME type mismatch. scenario.attach(bytes, "image/jpeg", "name") when the screenshot is actually PNG (Selenium's default) causes the image not to render in some reporters. Always use "image/png" for OutputType.BYTES screenshots.

🎯 Practice task

Set up all three reporting layers and compare their output. 45 minutes.

  1. Add all three plugins to the runner: pretty, html:target/cucumber-reports/report.html, json:target/cucumber-reports/report.json, and AllureCucumber7Jvm.
  2. Add maven-cucumber-reporting to pom.xml. Run mvn verify — open target/cucumber-html-reports/overview-features.html and browse the feature breakdown.
  3. Run allure serve target/allure-results — compare the Allure view with the masterthought view. Note which shows more detail per step.
  4. Fail one scenario deliberately (break an assertion). Run again. Confirm the screenshot appears embedded in all three report formats.
  5. Add the junit:target/cucumber-reports/report.xml plugin. Open the XML and find the <testcase> element for your failed scenario — this is what CI parsers read.
  6. Stretch: add the <testFailureIgnore>true</testFailureIgnore> flag to Surefire and run mvn verify with a failing test. Confirm BUILD SUCCESS is reported while the reports still show the failure — the correct CI pattern for "run all tests, publish results, then fail the pipeline based on the JUnit XML".

This completes Chapter 4. Chapter 5 covers BDD in practice with stakeholders — Three Amigos, living documentation, and how to scale BDD on a real team.

// tip to track lessons you complete and pick up where you left off across devices.