Allure Reporting with Playwright: The Complete Guide
The built-in Playwright HTML report is great for local debugging, but the moment you need rich dashboards, historical trends, severity grouping, and BDD-style steps that non-engineers can actually read, it starts to feel thin. Playwright Allure reporting fills that gap by turning your test runs into an interactive report with attachments, categories, and trend graphs. In this complete guide you will learn how to install Allure, wire it into your Playwright config, enrich tests with steps and metadata, and publish the report in CI.
π Want to master this with real projects? Join the Playwright Automation Mastery course at The Testing Academy.
Contents
Why use Allure instead of the default Playwright report?
Playwright already ships a polished HTML reporter, so it is fair to ask why you would add another tool. The answer is audience and history. The default report is a per-run snapshot optimized for developers chasing a flaky test. Allure is optimized for teams and stakeholders who want to see how quality is trending over weeks, slice failures by feature or severity, and read a clean step-by-step narrative without opening a trace file.
| Capability | Default Playwright HTML | Allure |
|---|---|---|
| Per-run results | Yes | Yes |
| Trace + video attachments | Yes | Yes |
| Historical trends across runs | No | Yes |
| Severity / feature grouping | No | Yes |
| BDD-style nested steps | Limited | Rich |
| Failure categories (flaky vs product bug) | No | Yes |
| Requirement / TMS links | No | Yes |
In practice many teams keep both: the Playwright report for fast local triage and Allure as the shareable system of record published to CI. They are not mutually exclusive, and Playwright lets you register multiple reporters at once.
Installing and configuring the Allure Playwright reporter
Allure has two moving parts. The allure-playwright npm package is the reporter that runs inside Playwright and writes raw result files (one JSON per test) into an allure-results folder. The Allure command line tool then converts those raw results into the browsable HTML report. Install the reporter as a dev dependency first.
# Reporter that plugs into Playwright
npm install --save-dev allure-playwright
# Allure CLI to generate and open the report
# (Java 8+ must be on PATH; the CLI is a Java app)
npm install --save-dev allure-commandline
Next, register the reporter in playwright.config.ts. The reporter option accepts an array, so you can keep the line reporter for terminal output and add Allure alongside it. The detail, suiteTitle, and environmentInfo options let you control how much structure Allure infers and what shows up on the report’s environment widget.
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
retries: process.env.CI ? 2 : 0,
reporter: [
['line'],
['allure-playwright', {
detail: true,
resultsDir: 'allure-results',
suiteTitle: true,
environmentInfo: {
framework: 'Playwright',
node_version: process.version,
os: process.platform,
},
}],
],
use: {
baseURL: 'https://playwright.dev',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
],
});
Notice that trace, screenshot, and video are configured the way you normally would. Allure automatically picks up the artifacts Playwright produces and attaches them to the corresponding test in the report, so a failing test ships with its trace, screenshot, and video without any extra wiring.
Generating and opening the report
Run your tests as usual. The reporter writes raw results, then the CLI turns them into HTML. Add a couple of npm scripts so the whole team uses the same commands.
{
"scripts": {
"test": "playwright test",
"allure:generate": "allure generate allure-results --clean -o allure-report",
"allure:open": "allure open allure-report",
"allure:serve": "allure serve allure-results"
}
}
The difference between the two workflows matters. allure serve spins up a temporary local web server and is perfect for a quick look after running tests locally. allure generate writes a static allure-report folder you can archive, deploy to GitHub Pages, or publish as a CI artifact.
# Local run, then serve a throwaway report
npx playwright test
npm run allure:serve
# Or build a static report you can deploy
npm run allure:generate
npm run allure:open
One gotcha: the allure-results folder is cumulative unless cleaned. If you do not delete it between unrelated runs you can end up mixing stale results into a fresh report. The --clean flag on allure generate only wipes the output folder, not the input, so clear allure-results yourself at the start of a fresh run when needed.
Adding steps, attachments, and metadata
Out of the box, Allure already records Playwright’s own steps because test.step() maps directly to Allure steps. Wrapping logical chunks of your test in test.step() instantly gives you a readable, collapsible breakdown in the report.
import { test, expect } from '@playwright/test';
test('search returns relevant docs', async ({ page }) => {
await test.step('Open the docs homepage', async () => {
await page.goto('/');
await expect(page).toHaveTitle(/Playwright/);
});
await test.step('Run a search for "locator"', async () => {
await page.getByRole('button', { name: 'Search' }).click();
await page.getByPlaceholder('Search docs').fill('locator');
await expect(page.getByRole('listbox')).toBeVisible();
});
});
For richer metadata, import the Allure runtime API directly. It exposes helpers to set severity, owner, tags, links, and to attach arbitrary content such as JSON payloads or API responses. The labels you set drive the grouping and filtering widgets in the report.
import { test, expect } from '@playwright/test';
import { allure } from 'allure-playwright';
test('checkout applies the discount code', async ({ page, request }) => {
// Metadata that drives Allure grouping and filters
await allure.epic('Commerce');
await allure.feature('Checkout');
await allure.story('Discount codes');
await allure.severity('critical');
await allure.owner('payments-team');
await allure.tags('regression', 'smoke');
await allure.link('https://jira.example.com/CART-42', 'CART-42', 'issue');
await allure.step('Fetch the cart via API', async () => {
const res = await request.get('/api/cart/123');
expect(res.ok()).toBeTruthy();
// Attach the raw JSON body for debugging in the report
await allure.attachment('cart.json', await res.text(), 'application/json');
});
await allure.step('Apply the code in the UI', async () => {
await page.goto('/cart');
await page.getByLabel('Promo code').fill('SAVE10');
await page.getByRole('button', { name: 'Apply' }).click();
await expect(page.getByTestId('total')).toContainText('$90.00');
});
});
Attachments are not limited to JSON. You can attach plain text logs, CSV exports, HTML snippets, or binary files such as a manually captured screenshot buffer. Because Allure renders attachments inline, a failing API step that ships its response body usually tells you what went wrong without ever opening a trace.
Severity, categories, and flaky test triage
Severity is more than decoration. When a nightly run produces fifty failures, sorting by critical versus minor tells you what to fix first. Allure also supports a categories.json file dropped into allure-results that classifies failures using regular expressions, so you can automatically split "product defects" from "test infrastructure problems."
[
{
"name": "Product defects",
"matchedStatuses": ["failed"],
"messageRegex": ".*expect.*"
},
{
"name": "Infrastructure problems",
"matchedStatuses": ["broken", "failed"],
"messageRegex": ".*(Timeout|ECONNREFUSED|net::ERR).*"
}
]
Combine this with Playwright’s built-in retries. When a test passes only after a retry, Allure marks it as flaky and surfaces it in a dedicated tab, so you can keep the suite green while still tracking instability instead of hiding it.
History and trends across runs
The single most valuable Allure feature for teams is trend history, and it is also the one most people forget to configure. Trends work by copying the history subfolder from your previous report into the new allure-results before you generate. Skip this step and every report looks like run number one with no graph.
# Carry forward history so trend graphs populate
if [ -d allure-report/history ]; then
cp -r allure-report/history allure-results/
fi
npx playwright test
allure generate allure-results --clean -o allure-report
In CI this usually means restoring the previous report from a cache or artifact store, copying its history folder forward, running tests, and regenerating. Once history exists, Allure draws pass/fail trend lines, duration trends, and a retries chart that make regressions obvious at a glance.
π Level Up Your Playwright
From locators to CI pipelines β build a production-grade Playwright + TypeScript framework step by step.
Running Playwright Allure reporting in CI
The whole point of Playwright Allure reporting is a shareable report that lives somewhere your team can reach. Here is a GitHub Actions workflow that installs dependencies, runs the tests, restores history, generates the report, and uploads it as an artifact. The if: always() guard ensures the report is published even when tests fail, which is exactly when you need it most.
name: e2e
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- uses: actions/setup-java@v4
with: { distribution: temurin, java-version: 17 }
- run: npm ci
- run: npx playwright install --with-deps
# Restore previous history for trend graphs
- uses: actions/cache@v4
with:
path: allure-report/history
key: allure-history-${{ github.run_id }}
restore-keys: allure-history-
- name: Run tests
run: npx playwright test
continue-on-error: true
- name: Build Allure report
if: always()
run: |
[ -d allure-report/history ] && cp -r allure-report/history allure-results/ || true
npx allure generate allure-results --clean -o allure-report
- name: Upload Allure report
if: always()
uses: actions/upload-artifact@v4
with:
name: allure-report
path: allure-report
For a hosted, always-on report, deploy the generated allure-report folder to GitHub Pages, Netlify, or an S3 bucket instead of (or in addition to) uploading the artifact. Because the report is fully static HTML, any static host works, and stakeholders can bookmark a single URL that always shows the latest run with full history.
Best practices for clean Allure reports
- Prefer
test.step()for behavior and the Allure runtime API for metadata; do not duplicate the same wording in both. - Set
epic,feature, andstoryconsistently so the Behaviors tab becomes a real living test inventory. - Attach API responses and computed values, not whole DOM dumps, so the report stays readable.
- Always clean
allure-resultsat the start of a fresh run, and always carryhistoryforward between runs. - Keep the default Playwright HTML reporter for local debugging and let Allure be the published source of truth.
- Use
categories.jsonto separate product bugs from infrastructure noise so triage is fast.
Followed together, these habits turn a raw pile of pass/fail results into a report a product manager can read and an engineer can debug from. That dual audience is the real reason Playwright Allure reporting earns its place in a mature automation stack: it gives developers the trace and the stakeholders the trend, from the exact same test run.
FAQ
Do I need Java installed to use Allure with Playwright?
Yes, for generating the HTML report. The allure-playwright reporter is pure JavaScript and writes raw JSON results without Java. But the Allure command line tool that converts those results into the browsable report is a Java application, so you need a JRE (Java 8 or newer) on your PATH for allure generate, allure serve, and allure open.
Why is my Allure report missing trend graphs?
Trends require history. Allure only draws trend lines when a history folder from the previous report is copied into allure-results before you run allure generate. If you regenerate from scratch every time without carrying history forward, each report looks like a brand-new first run. In CI, cache or store the previous report and copy its history folder into the new results.
Can I keep the default Playwright HTML report and Allure at the same time?
Absolutely. Playwright’s reporter option accepts an array of reporters, so you can list ['html'] (or ['line']) alongside ['allure-playwright', {...}]. They run from the same test execution with no extra cost, letting you use the native report for fast local triage and Allure as the shareable, history-aware report you publish to CI.
π Master Playwright End to End
Join hundreds of SDETs building real automation frameworks. Lifetime access, hands-on projects, and a job-ready portfolio.
