Jenkins CI
Serenity/JS integrates with Jenkins to run your acceptance tests and publish interactive HTML reports with trend history, flaky test detection, and error clustering.
In this guide, you'll learn how to configure Jenkins pipelines that:
- Run Serenity/JS test scenarios using the official Serenity/JS Docker image
- Publish the HTML Reporter output using the HTML Publisher plugin
- Preserve execution history across builds for trend analysis
Before you start
Set up a working Serenity/JS test suite using one of the official Serenity/JS Project Templates, or add Serenity/JS to your existing project by following the Serenity/JS installation guide.
If you're new to Serenity/JS, follow the tutorial to learn more about the framework.
Running Serenity/JS on Jenkins
Jenkins pipelines can run inside Docker containers using the agent { docker } directive.
To ensure a stable, reproducible testing environment, use the official Serenity/JS Docker image as your build agent. It comes pre-configured with:
- The latest Long-Term Support (LTS) version of Node.js
- All Playwright browser engines, plus stable Chrome and Edge
- OpenJDK Java Runtime Environment (for teams also using Serenity BDD Reporter)
Running tests inside a container eliminates environment drift between developer machines, Jenkins agents, and other CI environments. Browser versions, system dependencies, and font rendering all stay consistent — reducing flaky failures caused by infrastructure differences rather than product bugs.
Prerequisites
Ensure the following Jenkins plugins are installed:
- Docker Pipeline — enables Docker-based build agents
- HTML Publisher — publishes HTML reports in the Jenkins UI
Single-module project
A single-module project has one test suite that runs in a single pipeline. This is the most common setup for small to medium projects.
The HtmlReporter crew member handles both data collection and report generation automatically — no separate aggregation step is needed.
Basic pipeline
The --ipc=host argument prevents Chromium from running out of shared memory in containerised environments.
Without it, browser tests may crash with "out of memory" errors on agents with limited /dev/shm.
Preserving trend history
To enable trend analysis across builds, restore the previous report's test-runs/ directory before running tests.
The simplest approach is to archive the report and use the Copy Artifact plugin to restore it from the last successful build:
How trend history works:
- The "Restore history" stage copies
test-runs/from the last successful build into the workspace. - When tests run, the
HtmlReporterwrites new data toreports/serenity-js/test-runs/<runId>/and aggregates all available runs into the final report. - After tests complete,
archiveArtifactspreserves the full report directory for the next build to restore.
Use the maxHistory option to control how many runs are retained.
The "Restore history" stage requires the Copy Artifact plugin.
Multi-module project
A multi-module project runs tests across multiple parallel stages — for example, testing separate applications, browser variants, or sharded test suites. Each stage produces its own test data, and a final stage aggregates everything into one report.
Example: admin-ui and customer-ui
Consider a monorepo with two UI modules, each with its own test suite:
my-project/
├── modules/
│ ├── admin-ui/
│ │ ├── spec/
│ │ └── playwright.config.ts
│ └── customer-ui/
│ ├── spec/
│ └── playwright.config.ts
└── package.json
Step 1: Configure each module to archive data only
In each module's playwright.config.ts, use TestRunArchiver instead of the full HtmlReporter:
import { defineConfig } from '@playwright/test';
import type { SerenityFixtures, SerenityWorkerFixtures } from '@serenity-js/playwright-test';
export default defineConfig<SerenityFixtures, SerenityWorkerFixtures>({
testDir: './spec',
reporter: [
['line'],
['@serenity-js/playwright-test', {
crew: [
['@serenity-js/html-reporter:TestRunArchiver', {
outputDirectory: './reports/serenity-js',
specDirectory: './spec',
}],
]
}]
],
});
Step 2: Run tests in parallel and aggregate
Use Jenkins parallel stages to run modules concurrently, then aggregate in a final stage:
What happens:
- Both modules run in parallel. Each produces a
test-runs/directory in its ownreports/serenity-js/. - The "Aggregate report" stage combines all module data plus the restored historical data into a single report.
- The
postblock archives the combined report and publishes it via the HTML Publisher plugin.
Controlling report history
The maxHistory option limits how many test runs are retained.
Without it, the report grows indefinitely.
['@serenity-js/html-reporter', {
outputDirectory: './reports/serenity-js',
maxHistory: 20, // keep the last 20 runs
}]
For the CLI aggregate command:
npx @serenity-js/html-reporter aggregate \
--input "..." \
--output ./reports/serenity-js \
--max-history 20
A good starting value is the number of builds you'd realistically compare when investigating a regression. For most teams, 10–20 runs provides useful trend data without bloating artifact storage.
Generating JUnit reports
Jenkins natively recognises JUnit XML reports and surfaces test results in the build dashboard, including trend graphs and failure details.
Serenity/JS integrates with the native reporters offered by all supported test runners, including those producing JUnit reports:
- Playwright Test JUnit reporter
- Cucumber.js JUnit formatter
- Mocha JUnit reporter
- Jasmine JUnit reporter
- WebdriverIO JUnit reporter
To surface test results in Jenkins, add a junit post step:
post {
always {
junit(
testResults: 'reports/junit-results.xml',
allowEmptyResults: true,
)
publishHTML(target: [
reportName: 'Serenity Report',
reportDir: 'reports/serenity-js',
reportFiles: 'index.html',
keepAll: true,
alwaysLinkToLastBuild: true,
allowMissing: true,
])
}
}
By default, Jenkins blocks inline JavaScript in published HTML reports via its Content Security Policy. The Serenity/JS HTML Report requires JavaScript to function. To allow it, configure the CSP header in Manage Jenkins → Script Console:
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")
For a persistent fix, add this to your Jenkins startup arguments or use the Permissive Script Security plugin.
Using Serenity BDD Reporter
If you're using @serenity-js/serenity-bdd instead of the HTML Reporter,
your pipeline needs a serenity-bdd run step after tests complete to generate the HTML report.
The official Serenity/JS Docker image includes OpenJDK, so no additional Java setup is required.
stage('Test') {
steps {
sh 'npm test'
// package.json: "test": "failsafe clean test:execute test:report"
// where test:report runs: serenity-bdd run
}
}
post {
always {
publishHTML(target: [
reportName: 'Serenity BDD Report',
reportDir: 'target/site/serenity',
reportFiles: 'index.html',
keepAll: true,
alwaysLinkToLastBuild: true,
allowMissing: true,
])
}
}
See the Serenity BDD Reporter documentation for full configuration, or consider migrating to the HTML Reporter for a simpler CI setup with built-in trend analysis.
Learn more
- HTML Reporter — configuration, CI integration patterns, migration from Serenity BDD
- Serenity/JS Docker images — pre-configured container images for CI
- Serenity/JS Project Templates — pre-configured starters with CI workflows
- Jenkins Pipeline documentation — pipeline syntax and configuration reference
- Jenkins Docker Pipeline plugin — running builds inside Docker containers