Skip to main content

PyPI version Python Development Status Maintenance PyPI License


💡 pytest-better-report

A pytest plugin that writes a structured report of every run: a JSON file per test, a JSON file for the run with CI metadata (repo, PR/MR, pipeline, commit), and an optional Markdown summary. Includes a CLI to compare two runs.


📦 Installation

uv add pytest-better-report

🚀 Features

  • ✅ Structured JSON — test_results.json (one entry per test) and execution_results.json (the run)
  • ✅ CI traceability — repo name, PR / MR number, pipeline number and commit in the run report
  • ✅ Markdown summary — a table of every test with status, duration and message
  • ✅ Structured failure data — raise with a JSON object as the message to record it as data
  • ✅ Compare two runs — better_report_compare lists missing tests and status differences
  • ✅ Plays well with other plugins — statuses come from pytest's final reports, whatever the plugin order
  • ✅ Zero footprint without the flag — nothing is registered, no hook runs

🛠️ How to Use

pytest --better-report --md-report --pr-number=123 --commit="$GIT_SHA"

Files are written to results_output/ (or <output-dir>/results_output/):

File Content
test_results.json One entry per test: name, file, class, parameters, markers, status, times, exception, user properties
execution_results.json The run: status, start / end / duration, CI metadata, environment, optionally the pytest command
test_report.md With --md-report: a table of all tests and a summary by status

⚙️ Flags

Flag Description
--better-report Enable the report
--output-dir=DIR Write the files to DIR/results_output/
--md-report Also write test_report.md
--traceback Add the crash location and traceback frames to each exception
--repo-name, --pr-number, --mr-number, --pipeline-number, --commit CI metadata for execution_results.json
--pytest-command Record the pytest command line in execution_results.json
--pytest-xfail-strict Treat an unexpected pass (XPASS) as a failure of the run
--result-each-test Log each test's result after it runs
--log-collected-tests Log every collected test at the start (works without --better-report too)

📊 Statuses

Each test gets one status in test_results.json. The run as a whole gets execution_info.execution_status in execution_results.json: failed if at least one test has a status marked "Yes" in the last column, otherwise passed.

This is the report's own verdict on the run, written into the file. It is separate from pytest's exit code, which this plugin doesn't change.

Test status Meaning Makes execution_status = failed
passed Passed No
failed Failed or errored in setup, call or teardown Yes
skipped Skipped (marker, fixture, or a plugin that converted the outcome) No
xfailed Expected failure No
xpassed Unexpected pass Only with --pytest-xfail-strict
collected Collected but not run (e.g. the run stopped early) No

▶️ Usage Examples

Record structured failure data

import json

def test_api():
    response = call_api()
    if response.status != 200:
        raise AssertionError(json.dumps({"status": response.status, "body": response.text}))

The exception is recorded as {"status": ..., "body": ...} instead of plain text.

Compare two runs

better_report_compare -a main/test_results.json -b branch/test_results.json --fail-on-diff

Lists tests missing from either side and tests whose status changed; exits non-zero with --fail-on-diff when there are differences. --test-file-name limits the comparison to one test file.


🔁 Migrating from pytest-plugins

This plugin was previously better_report in pytest-plugins. Flags, file names and the JSON schema are unchanged. Both register the same options, so don't install them together until you're on a pytest-plugins release without it. Differences you may notice:

  • A test that errors in teardown is now failed (it was reported as passed).
  • The failed-skipped status no longer exists; converted failures are skipped, with the reason in test_user_properties.
  • The logger is named pytest_better_report.
  • --add-parameters was removed. Parameters are always recorded in test_parameters; in ELK / Kibana query them as test_parameters.<name> instead of <name>. Passing the flag now fails with "unrecognized arguments".

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-addition
  3. Make your changes
  4. Commit your changes: git commit -m 'Add my addition'
  5. Push to the branch: git push origin feature/my-addition
  6. Open a Pull Request

Additions that promote clean, productive, and maintainable development are always welcome.


📄 License

MIT License — see LICENSE for details.


🙏 Thanks

Thanks for exploring this repository!
Happy coding!

GitHub   PyPI   Blog   LinkedIn

Metadata

Release files for pytest-better-report 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-better-report 1.0.3
File Size Uploaded Provenance Actions
pytest_better_report-1.0.3.tar.gz 15.9 kB Without provenance Details for pytest_better_report-1.0.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pytest-better-report 1.0.3
File Interpreter ABI Platform Actions
pytest_better_report-1.0.3-py3-none-any.whl Python 3 none any Details for pytest_better_report-1.0.3-py3-none-any.whl

Total release size: 32.6 kB

Release files / pytest_better_report-1.0.3.tar.gz

Download URL pytest_better_report-1.0.3.tar.gz
Size 15.9 kB
Tags Source
SHA-256 checksum
How to use checksums
272340e971b53a6c0c2ddc6c3d71fde0c0016977864a9b7424b224c42ce68920
BLAKE2b-256 checksum
How to use checksums
62273bac0d4b4497a448057c33a50aed71e4e8c92eafbd02e98ea40e86abd7e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / pytest_better_report-1.0.3-py3-none-any.whl

Download URL pytest_better_report-1.0.3-py3-none-any.whl
Size 16.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
14c3645e438f067af9bb4816691584a6f717db56171c1d23cd28de7adbe9d677
BLAKE2b-256 checksum
How to use checksums
82e31b8c77f024b514e483309783f20a17fe34116bf18bec8b94cc5ae14dafef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for pytest-better-report 1.0.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page