|

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.

CapabilityDefault Playwright HTMLAllure
Per-run resultsYesYes
Trace + video attachmentsYesYes
Historical trends across runsNoYes
Severity / feature groupingNoYes
BDD-style nested stepsLimitedRich
Failure categories (flaky vs product bug)NoYes
Requirement / TMS linksNoYes

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, and story consistently 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-results at the start of a fresh run, and always carry history forward between runs.
  • Keep the default Playwright HTML reporter for local debugging and let Allure be the published source of truth.
  • Use categories.json to 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.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.