allure-reports
Configures Allure Report (test-runner adapter install, `allure-results` directory wiring, `categories.json` for failure classification, `history-trend.json` retention via the copy-history-between-runs pattern), runs the Allure CLI to convert `allure-results` to a static HTML site, and uploads the report as a CI artifact. Use when the team needs richer test reporting than JUnit XML - step-level attachments, per-test history, retry tracking, and severity / epic / feature labeling across framework-agnostic adapters (pytest, Jest, JUnit, TestNG, NUnit, Mocha). As a rich static HTML report generator, it is the open-source alternative to the sunset ExtentReports (JVM/.NET per-test HTML narrative); for hosted cross-run flakiness analytics rather than a static per-run report use currents-integration.
Install with skills.sh (any agent)
npx skills add testland/qa --skill allure-reportsallure-reports
Overview
Allure Report is "an open-source framework-agnostic test result visualization tool" that "transforms test execution data into clear, interactive HTML reports" (allure-docs (opens in new window)). It "supports testing frameworks across JavaScript, Python, Java, C#, PHP, and Ruby" with 30+ adapters (allure-docs (opens in new window)).
Allure's two-stage workflow:
The two artifacts are kept separate intentionally: results are runner-emitted; the report is a static deliverable.
When to use
If the team only needs JUnit pass/fail and the CI already surfaces that, see junit-xml-analysis - that's a much lighter dependency.
Step 1 - Install the framework adapter
Each runner has a per-language adapter that writes to allure-results/. Examples:
| Framework | Package / coordinate | Output dir env var (typical) |
|---|---|---|
| pytest | pip install allure-pytest | --alluredir=allure-results |
| Jest | npm i -D allure-jest | outputFolder config |
| Mocha | npm i -D allure-mocha | outputFolder config |
| JUnit 5 | org.junit.platform:junit-platform-launcher + io.qameta.allure:allure-junit5 | allure.results.directory system property |
| TestNG | io.qameta.allure:allure-testng | allure.results.directory |
| NUnit / xUnit | NuGet Allure.NUnit / Allure.Xunit | allureConfig.json directory |
Adapter docs are at the framework-specific subpaths under allurereport.org/docs/ (allure-docs (opens in new window)).
The output of running tests with the adapter installed is a directory of per-test JSON files (<uuid>-result.json, <uuid>-container.json, plus attachment-<uuid>.<ext> files for screenshots / logs).
Step 2 - Generate the static report
Install the Allure CLI (allure-docs (opens in new window) linked from "Installation"):
# Node-based (cross-platform):
npm install -g allure-commandline
# Or via Scoop / Homebrew / apt - see allurereport.org/docs/ install pages.Generate from the results directory:
allure generate allure-results --clean -o allure-report--clean removes the previous allure-report/ before regenerating; -o sets the output dir.
To preview locally:
allure open allure-reportOr in one shot (useful in dev - runs a temp server with a freshly generated report):
allure serve allure-results(See allurereport.org/docs/ for the CLI reference; specific flags have evolved across Allure 2.x and Allure 3 - pin a version in CI to avoid drift.)
Step 3 - Configure failure categories
Per allure-categories (opens in new window), categories.json placed in allure-results/ defines custom failure classification. Each entry matches by message regex, trace regex, and result statuses (failed, broken, passed, skipped, unknown):
[
{
"name": "Ignored tests",
"messageRegex": ".*ignored.*",
"matchedStatuses": ["skipped"]
},
{
"name": "Infrastructure problems",
"messageRegex": ".*RuntimeException.*",
"matchedStatuses": ["broken"]
}
]Per allure-categories (opens in new window), category objects also support traceRegex (matches against stack trace) and flaky (boolean) to mark a category as flaky-by-default.
"The array order determines the matching sequence Allure applies when categorizing test results." (allure-categories (opens in new window))
So order from most-specific to least-specific. A "DB connection refused" category should precede a generic "Infrastructure" category.
Step 4 - Wire history retention
Per allure-history (opens in new window), history is what drives the trends panel ("first failed", "last passed", flake / retry rate over time):
"Allure Report uses a history ID to link test results across multiple runs. This identifier is automatically calculated based on the test's fully-qualified name and its parameters."
For Allure 2 (the broadly-deployed version), enabling history is manual (allure-history (opens in new window)):
In CI, that becomes:
# Before running tests
mkdir -p allure-results
if [ -d previous-allure-report/history ]; then
cp -r previous-allure-report/history allure-results/
fi
# Run tests (writes to allure-results/)
npm test
# Generate
allure generate allure-results --clean -o allure-report
# Save the history slice for next time
# (Upload allure-report/ as an artifact; download into previous-allure-report/ on next run.)Per allure-history (opens in new window): "If you follow such a routine regularly, Allure will each time keep data from up to 20 latest reports in allure-results/history."
For Allure 3 (allure-history (opens in new window)):
"Allure 3 simplifies this by using a single JSONL history file. You configure it in your settings file with a
historyPathparameter."
Step 5 - Distinguish retries from history
Per allure-history (opens in new window):
"Retries: Multiple runs of the same test within a single launch (same
allure-resultsdirectory).""History: Links to the same test across different launches, enabling trend analysis and stability tracking."
Don't clear allure-results between retries within a run - that collapses retry data. Do clear it between launches (different commits / runs) - only history/ subdir is preserved.
Step 6 - CI integration (GitHub Actions)
# .github/workflows/test-with-allure.yml
name: test-with-allure
on:
pull_request:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with: { node-version: '20' }
- name: Restore previous Allure history
uses: actions/download-artifact@v4
with:
name: allure-history
path: previous-allure-report
continue-on-error: true # First run on a branch has no history
- name: Seed history into results dir
run: |
mkdir -p allure-results
if [ -d previous-allure-report/history ]; then
cp -r previous-allure-report/history allure-results/
fi
- name: Run tests with Allure adapter
run: npm test # adapter writes to allure-results/
- name: Install Allure CLI
run: npm install -g allure-commandline
- name: Generate report
if: always()
run: allure generate allure-results --clean -o allure-report
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: allure-report
path: allure-report
retention-days: 30
- name: Save history for next run
if: always() && github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v4
with:
name: allure-history
path: allure-report/history
retention-days: 90if: always() on the report-generation steps is critical - Allure matters most on failure.
For Allure history hosted on GitHub Pages, the simple-elf/allure-report-action GitHub Action automates the publish-to-Pages workflow (third-party, not first-party Allure tooling).
Step 7 - Add metadata to test cases
Allure's value compounds with metadata. The adapter exposes per-language helpers; the canonical labels are severity (blocker / critical / normal / minor / trivial), epic / feature / story (for BDD-style grouping), and owner.
# pytest example
import allure
@allure.severity(allure.severity_level.CRITICAL)
@allure.epic('Checkout')
@allure.feature('Promo codes')
@allure.story('Apply at checkout')
def test_apply_promo_lowercase():
...// Jest / Mocha example
import { allure } from 'allure-jest';
allure.severity('critical');
allure.epic('Checkout');
allure.feature('Promo codes');Severity drives the "blocker" / "critical" filter on the report's overview; epic / feature / story drive the BDD-grouped view. Without them, the report is a flat list - usable but missing Allure's main selling point.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Skipping the history step | Trends panel is empty; retry/flake history can't be tracked across runs. | Wire the copy-history pattern (Step 4) per allure-history (opens in new window). |
Clearing allure-results mid-run | Retry information is lost - retries appear as separate failed launches. | Clear only between launches; preserve history/ subdir per allure-history (opens in new window). |
categories.json ordered least-specific first | Generic "Infrastructure" category catches everything; specific categories never match. | Order most-specific first per allure-categories (opens in new window). |
| Allure as a substitute for JUnit XML in PR gating | Allure's report is for humans, not gating; JUnit XML is the gate. | Emit both; gate on JUnit; surface Allure as artifact. |
| One Allure adapter version + a different CLI version | Schema drift between adapter (results writer) and CLI (results reader); empty / corrupt report. | Pin both to compatible versions; bump together per allure-docs (opens in new window). |
| Adapter installed but no metadata | Report is a flat pass/fail list - same value as JUnit XML. | Add severity / epic / feature / story (Step 7). |
Treating <uuid>-result.json files as durable | The file naming and schema are per-Allure-version internal contracts. | Don't post-process raw allure-results/ files; consume the generated allure-report/data/*.json instead. |
Limitations
References
Related skills
coverage-diff-reporter
Builds a per-PR coverage delta report from any pair of LCOV / Cobertura / JSON coverage outputs (current run + baseline from the merge target) - emits a per-file table with line% / branch% deltas, called-out new files, hidden drops (overall +0.1pp but one file -8pp), and a single-line PR-comment summary. Use when the team has coverage in CI but needs human-readable PR feedback that points at the specific file the reviewer should focus on, not just an aggregate number.
coverage-py-analysis
Configures coverage.py for Python projects - wires `coverage run` (replacing `python` for instrumentation), enables branch coverage via the `--branch` flag or `branch = True` config, manages the `.coverage` data file (single-process and `combine` for parallel pytest-xdist runs), authors `.coveragerc` with `source` / `omit` / `fail_under`, and emits the format the downstream tool needs (`coverage report` for terminal, `coverage xml` for Cobertura, `coverage html` for human review, `coverage lcov` for SaaS, `coverage json` for programmatic post-processing). Use for any Python test stack (pytest, unittest, nose) that needs PR-time coverage signal.
currents-integration
Wires Currents.dev cross-run test analytics into a Playwright suite: installs `@currents/playwright`, authors `currents.config.ts` (env-sourced `recordKey` + `projectId`), registers `currentsReporter()`, enables trace/video/screenshot artifacts, and runs via `npx pwc` so per-test traces stream to the Currents dashboard with over-time flakiness, slowest-test, and pass-rate trends. Use when a Playwright suite needs hosted cross-run suite-health analytics; for a static per-run report use extentreports or allure-reports, and to sync results into TestRail / Xray / Zephyr test management use test-management-sync.
jacoco-analysis
Configures JaCoCo for JVM projects (Java / Kotlin / Scala / Groovy) - wires the runtime agent via `jacoco-maven-plugin` `prepare-agent`, generates per-build reports (HTML / XML / CSV) via the `report` goal, gates the build via the `check` goal with element / limit / minimum rules, parses the six native counters (instructions, branches, lines, methods, classes, cyclomatic complexity), and converts JaCoCo XML to LCOV / Cobertura when downstream tools need a different format. Use when the JVM build is Maven / Gradle and the team wants the canonical JVM coverage tool - or to convert JaCoCo output for cross-language coverage aggregation.
junit-xml-analysis
Explains CI test numbers that disagree with what the suite actually did - a 'slowest tests' list dominated by the wrong suite, a release gate or dashboard reading only the summary attributes on the suite element and never the cases below them, or a pass rate that quietly counts skipped tests as passes. Parses JUnit-format XML (the interchange format Jenkins, GitHub Actions, GitLab, Buildkite, and CircleCI all ingest) into per-suite and per-case metrics tables - passed / failed / errored / skipped, time, classname, message, stack - groups failures by classname for trend analysis, and separates new failures from flakes by cross-referencing the `flakyFailure` and rerun elements. Use when a report, gate, or metric derived from test results cannot be trusted.
lcov-analysis
Parses both mainstream coverage interchange formats: LCOV `.info` text files (produced by gcov, llvm-cov, Coverage.py via `py2lcov`, JaCoCo via `xml2lcov`, Devel::Cover, Jest via `lcov` reporter, NYC, and most others) and Cobertura XML (coverage-04.dtd - emitted by JaCoCo, coverage.py `--xml`, Jest's `cobertura` reporter, coverlet, gocover-cobertura; full parser in references/cobertura.md). Extracts per-file line / function / branch metrics from the canonical record keywords (TN/SF/FN/FNDA/FNF/FNH/BRDA/BRF/BRH/DA/LH/LF), computes the diff vs a baseline, and emits per-file gating verdicts. Use for PR coverage gates that don't depend on a specific language runtime, whichever of the two formats the CI emits.
test-coverage-targeter
Builds a "what to test next" recommendation by combining a coverage report (LCOV / Cobertura / coverage.py JSON / Jest JSON / JaCoCo XML) with the PR's `git diff`, ranking uncovered branches by risk × cost - risk weighted by McCabe cyclomatic complexity and code-churn frequency, cost weighted by the unit-test pyramid layer (unit tests cheaper than integration than E2E). Also carries the coverage debt ledger: a weekly per-file drift report over N historical main runs flagging `falling` (line% slid >M pp from peak), `stale` (flat coverage + high churn), and `orphan` (lost last covering test) files, whose rows feed the same targeting. Emits a prioritized list with concrete file:line targets and the test layer recommended for each. Use when a team has the budget to write 5 - 10 new tests and needs help picking which uncovered code to target first instead of blindly chasing 100% coverage, or when specific modules are eroding silently while whole-repo coverage looks fine.
test-management-sync
Syncs automated test results into test management tools - TestRail (standalone, `add_run` + batched `add_results_for_cases`), Xray for Jira (JWT auth + `/api/v2/import/execution/*`), and Zephyr Scale (Bearer token + `/testexecutions`) - from CI. The body carries the vendor-independent push-results workflow (map tests to case IDs, open a run / execution / cycle per build, batch results back, close on main only, run as an `if: always()` step) with TestRail as the worked example; full vendor specifics live in references/ (testrail.md, xray.md, zephyr.md). Use when automated suites must keep the team's test management view in sync without a human copy-paste step; for hosted cross-run flakiness analytics rather than TCM sync use currents-integration, and for authoring / migrating test CASES rather than pushing results see qa-test-management's tcm-case-management.
test-run-summary-author
Build-an-X workflow that turns a structured test-run artifact (JUnit XML, Allure JSON, TestRail / Xray / Zephyr export) plus optional release context (version, build URL, deploy target) into a narrative markdown summary for release notes, an exec status update, or a stand-up Slack post. Distinct from the per-framework parsers junit-xml-analysis / allure-reports / coverage-diff-reporter, which emit structured tabular reports: this skill takes the same data and writes the human-readable narrative. Use when a manager needs a draft release note or stand-up summary from a single run; for cross-run trend analytics use currents-integration.