How to generate Cucumber test reports
Three ways to get readable Cucumber reports in Node.js: the built-in HTML formatter, cucumber-html-reporter from JSON, and publishing reports from CI.
This follows on from end-to-end test automation with Selenium and Cucumber. Terminal output is fine while you write tests, but when a run fails in CI, or you want to show results to someone else, you need a report: every feature, scenario and step, with timings, errors and screenshots.
Cucumber.js produces reports through formatters. You can use several at once, each writing to its own file.
Option 1: the built-in HTML report
Modern Cucumber (@cucumber/cucumber) has an HTML formatter built in. Nothing to install:
npx cucumber-js --format html:reports/cucumber-report.htmlOr set it once in cucumber.js, alongside the console output:
// cucumber.js
module.exports = {
default: {
paths: ["features/**/*.feature"],
require: ["features/**/*.js"],
format: ["progress-bar", "html:reports/cucumber-report.html"],
},
}The result is a single, self-contained HTML file you can open anywhere. It has a search box,
filters by status, and shows attachments, such as the screenshots our After hook adds when a
step fails:
// features/support/hooks.js
const { After, Status } = require("@cucumber/cucumber")
After(async function ({ result }) {
if (result?.status === Status.FAILED && this.driver) {
const png = await this.driver.takeScreenshot()
this.attach(Buffer.from(png, "base64"), "image/png")
}
await this.driver?.quit()
})For most projects, this is all you need.
Option 2: a Bootstrap-style report from JSON
If you prefer a dashboard with charts and custom metadata, write a JSON report and convert it with cucumber-html-reporter.
npm install --save-dev cucumber-html-reporterAdd a JSON formatter:
// cucumber.js
module.exports = {
default: {
paths: ["features/**/*.feature"],
require: ["features/**/*.js"],
format: ["progress-bar", "json:reports/cucumber-report.json"],
},
}Then a small script that turns the JSON into HTML:
// scripts/report.js
const reporter = require("cucumber-html-reporter")
reporter.generate({
theme: "bootstrap",
jsonFile: "reports/cucumber-report.json",
output: "reports/cucumber-report.html",
reportSuiteAsScenarios: true,
scenarioTimestamp: true,
launchReport: !process.env.CI, // open it in a browser locally, not in CI
metadata: {
"App version": process.env.APP_VERSION || "local",
Browser: "Chrome",
Platform: process.platform,
Executed: process.env.CI ? "CI" : "Local",
},
}){
"scripts": {
"test:e2e": "cucumber-js",
"test:e2e:report": "node scripts/report.js"
}
}Run the tests, then build the report. Use ; (or a posttest script) so the report is generated
even when tests fail:
npm run test:e2e; npm run test:e2e:reportScreenshots attached in hooks are embedded in the JSON, so they show up here too.
Option 3: publish reports from CI
Keep the report from every CI run as a downloadable artifact:
# .github/workflows/e2e.yml (steps)
- run: npm run test:e2e:headless
- run: npm run test:e2e:report
if: always()
- uses: actions/upload-artifact@v4
if: always()
with:
name: cucumber-report
path: reports/if: always() makes both steps run after a failure, which is exactly when you want the report.
Download it from the run's Summary page under Artifacts.
Keep reports out of git
Reports are build output. Add the folder to .gitignore:
reports/Which one to pick
| Built-in HTML | cucumber-html-reporter | |
|---|---|---|
| Install | Nothing | One dev dependency |
| Steps | One formatter | JSON formatter + a script |
| Screenshots | Yes | Yes |
| Charts and custom metadata | No | Yes |
Start with the built-in HTML formatter. Add the JSON route when you need charts or extra metadata for stakeholders.
