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 verifyThe 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 aggregateaggregate 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.featureThe 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/serenityJenkins
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.