Serenity BDD Reporting: Living Documentation From Your Tests

Serenity BDD Reporting: Living Documentation From Your Tests

Serenity BDD's reporting is the reason most teams choose it over plain JUnit + Selenium. The HTML report it generates is a stakeholder-readable summary of what was tested, what passed, and what failed — with screenshots, step-level details, and a requirements hierarchy. This guide covers the reporting system in depth.

What the Report Contains

The Serenity HTML report (target/site/serenity/index.html) has several sections:

Test Results tab: Every test with pass/fail/pending status, execution time, and step details.

Requirements tab: Features and stories derived from annotations (@Epic, @Feature, @Story) or Cucumber feature file structure. Shows coverage percentage.

Capabilities/Features tab: Top-level navigation through your test hierarchy.

Test Failures tab: All failed tests with screenshots, stack traces, and step at which failure occurred.

Generating the Report

Maven

mvn clean verify

The serenity-maven-plugin generates the report during the post-integration-test phase. The Serenity plugin must be configured:

<plugin>
    <groupId>net.serenity-bdd.maven.plugins</groupId>
    <artifactId>serenity-maven-plugin</artifactId>
    <version>4.1.20</version>
    <executions>
        <execution>
            <id>serenity-reports</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>aggregate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Without this, tests run but no HTML report is generated.

Gradle

plugins {
    id 'net.serenity-bdd.serenity-gradle-plugin' version '4.1.20'
}

serenity {
    projectKey = 'my-project'
}
./gradlew clean test aggregate

aggregate is the Serenity Gradle task that generates the HTML report.

Screenshot Configuration

Control when Serenity takes screenshots via serenity.conf:

serenity {
    # Options: FOR_EACH_ACTION, FOR_FAILURES, AFTER_EACH_STEP, DISABLED
    take.screenshots = FOR_FAILURES      # default — only on failure
    # take.screenshots = AFTER_EACH_STEP  # screenshot after every step (large reports)
}

FOR_FAILURES keeps reports small. AFTER_EACH_STEP produces a visual walkthrough useful for stakeholder demos but generates many files.

Screenshots for failed tests appear inline in the report at the step where the failure occurred.

Requirements Hierarchy

From JUnit Annotations

@Epic("E-Commerce Platform")
@Feature("Shopping Cart")
public class CartTest {

    @Test
    @Story("Add item to cart")
    void user_can_add_item_to_cart() { ... }

    @Test
    @Story("Remove item from cart")
    void user_can_remove_item() { ... }
}

This produces a hierarchy: E-Commerce Platform → Shopping Cart → story titles.

From Cucumber Feature Files

When using Serenity + Cucumber, the feature file location determines hierarchy:

src/test/resources/features/
  ecommerce/           → capability
    cart/              → feature
      cart.feature     → feature name from "Feature:" header
      checkout.feature
    payments/
      payment.feature

The Cucumber feature file's Feature:, @tags, and scenario names populate the Requirements section automatically.

Pending and Skipped Tests

Mark tests as pending (work in progress) without failing the build:

@Test
@Pending
void feature_not_yet_implemented() {
    // Will show as "Pending" in report, not failure
}
@wip
Scenario: Feature under development
  Given ...

Pending tests show in the report with a distinct status, giving stakeholders visibility into planned work.

Custom Report Configuration

serenity.conf options:

serenity {
    project.name = "MyApp Test Report"

    # Show full step details in report
    reports.show.step.details = true

    # Include stack traces in report
    verbose.steps = true

    # Report directory (relative to project root)
    outputDirectory = target/site/serenity

    # Title in HTML report header
    project.name = "MyApp — Automated Test Report"
}

CI Integration

GitHub Actions

- name: Run Serenity tests
  run: mvn clean verify -DBASE_URL=${{ vars.STAGING_URL }}

- name: Upload Serenity report
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: serenity-report
    path: target/site/serenity/
    retention-days: 30

# Optional: publish to GitHub Pages
- name: Deploy report to GitHub Pages
  if: github.ref == 'refs/heads/main'
  uses: peaceiris/actions-gh-pages@v3
  with:
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: target/site/serenity

Jenkins

stage('Test') {
    steps {
        sh 'mvn clean verify'
    }
    post {
        always {
            publishHTML([
                allowMissing: false,
                alwaysLinkToLastBuild: true,
                keepAll: true,
                reportDir: 'target/site/serenity',
                reportFiles: 'index.html',
                reportName: 'Serenity Report'
            ])
        }
    }
}

Reading the Report

Green bar at the top — percentage of passing tests. Anything below 100% needs attention.

Requirements section — shows which features have test coverage and which features have failures. This is the stakeholder-facing view: "Are our core features working?"

Clicking a scenario — opens the step-by-step execution with timestamps. For failures, the failing step is highlighted and a screenshot is shown.

Test data — parameterized tests (JUnit @ParameterizedTest or Cucumber Scenario Outline) show each data row as a separate result.

Serenity JIRA Integration

For teams using JIRA, Serenity can link test results to JIRA issues:

jira {
    url = "https://mycompany.atlassian.net"
    project = "MYAPP"
    username = ${JIRA_USER}
    password = ${JIRA_TOKEN}
}
@WithTag("MYAPP-123")
@Test
void user_can_login() { ... }

Test results appear in the linked JIRA issue automatically.

Summary

Serenity's reporting system is the strongest reason to choose it over bare JUnit + Selenium. The HTML report gives product owners a feature-by-feature view of test coverage and results without them needing to read code or interpret CI logs. Screenshots at failure points give developers enough context to diagnose issues without re-running tests.

The key configuration choices are screenshot frequency (use FOR_FAILURES for most projects), requirements hierarchy (either annotations or Cucumber file structure), and CI publishing (artifacts or GitHub Pages). Get these right once and the report becomes a living record of what the application does and whether it's working.

Read more

Start now free