Skip to main content

PyPI version Python Development Status Maintenance PyPI License


💡 pytest-reporter-html

A pytest plugin that automatically generates rich, interactive HTML test reports with zero-config log capture, named step tracking, exception rendering, and real-time filtering — open the file in any browser and start debugging.


📦 Installation

uv add pytest-reporter-html

🚀 Features

  • ✅ Zero-Config Log Capture — attaches to Python's root logger automatically; every logging.*() call is captured as a report event without any code changes
  • ✅ Named Steps — group events into collapsible, timed steps using the step context manager or decorator (sync and async); supports nested steps with automatic hierarchical numbering (1, 1.1, 1.2, 2, …)
  • ✅ Automatic Phase Steps — Setup, test body, and Teardown phases are created automatically for every test
  • ✅ Interactive HTML Report — real-time search, status filter (Passed/Failed), log-level filter (TRACE→ERROR), expand/collapse all, progress bar
  • ✅ Exception Rendering — full tracebacks captured and rendered as collapsible blocks; failed tests auto-expand
  • ✅ JSON + HTTP Visualisation — embedded JSON is syntax-highlighted; HTTP requests are shown with a generated cURL command and copy button
  • ✅ Automatic JSON Cleanup — intermediate per-test JSON files are deleted after the HTML is generated by default; use --keep-json to retain them
  • ✅ report_test_name Fixture — override the displayed test name at runtime (useful for parameterised tests)
  • ✅ Async Support — step works as both async with and an async def decorator

⚙️ Configuration

Enable the HTML report by adding --report-html to your pytest options:

# pytest.ini / pyproject.toml
[pytest]
addopts = --report-html

Or pass it directly on the command line:

pytest --report-html

CLI options

Option Default Description
--report-html off Generate an aggregated HTML report at session end
--keep-json off Keep intermediate per-test JSON files after HTML generation
--report-html-dir logs/test-reports Directory for the JSON/HTML output
--report-html-title Test Report Title of the HTML report

By default, the JSON files written during the run are deleted once the HTML report is produced. Pass --keep-json if you need them for other tooling:

pytest --report-html --keep-json

🛠️ How to Use

  1. Install the plugin: uv add pytest-reporter-html
  2. Enable HTML report generation by adding --report-html to your pytest options
  3. Run your tests normally with pytest
  4. Open logs/test-reports/TestReport_Latest.html in any browser
  5. (Optional) Use step to group log events into named, collapsible blocks

🚀 Quick Start

# pyproject.toml
[tool.pytest.ini_options]
addopts = "--report-html"
pytest

After the run, open the report:

logs/test-reports/TestReport_Latest.html

▶️ Usage Examples

Example 1: Named steps with logging

from custom_python_logger import get_logger
from pytest_reporter_html import step

logger = get_logger(__name__)

def test_user_lifecycle():
    with step("Create user"):
        logger.info("Creating a new user with role 'user'")

    with step("Update profile"):
        logger.info("Updating user profile to set role to 'admin'")

    with step("Verify changes"):
        logger.info("Verifying that the user's role has been updated to 'admin'")

Report output:

Test: test_user_lifecycle                                            PASSED
 ├── Step 1: Create user                                PASSED    120ms
 ├── Step 2: Update profile                             PASSED     45ms
 └── Step 3: Verify changes                             PASSED     30ms

Example 2: Nested steps

Steps can be nested to any depth. Each level gets a hierarchical number automatically (1.1, 1.2, 2.1, …).

from custom_python_logger import get_logger
from pytest_reporter_html import step

logger = get_logger(__name__)

def test_user_lifecycle():
    with step("Create user"):
        logger.info("Creating a new user with role 'user'")
        with step("Assign default role"):
            logger.info("Setting role to 'viewer'")
        with step("Send welcome email"):
            logger.info("Email dispatched")

    with step("Update profile"):
        logger.info("Updating user profile to set role to 'admin'")

    with step("Verify changes"):
        logger.info("Verifying that the user's role has been updated to 'admin'")

Report output:

Test: test_user_lifecycle                                            PASSED
 ├── Step 1: Create user                                PASSED    120ms
 │    ├── Step 1.1: Assign default role                 PASSED     30ms
 │    └── Step 1.2: Send welcome email                  PASSED     20ms
 ├── Step 2: Update profile                             PASSED     45ms
 └── Step 3: Verify changes                             PASSED     30ms

Sub-steps appear visually indented inside their parent step in the HTML report.


Example 3: step as a decorator

from custom_python_logger import get_logger
from pytest_reporter_html import step

logger = get_logger(__name__)

@step("Fetch user data")
def get_user(user_id: str) -> dict:
    logger.info(f"Fetching user {user_id}")
    return {"id": user_id, "active": True}

@step("Send notification")
async def notify(user_id: str) -> None:
    logger.info(f"Sending notification to user {user_id}")

def test_flow():
    user = get_user("u-1")   # → Step 1: Fetch user data
    assert user["active"] is True

Example 4: Failure output

When a test fails it auto-expands in the report, showing the failure message, stack trace, and all log events up to the point of failure:

from custom_python_logger import get_logger
from pytest_reporter_html import step

logger = get_logger(__name__)

def test_order_checkout():
    with step("Create order"):
        logger.info("Creating order with 3 items")

    with step("Checkout"):
        logger.info("Submitting checkout request")
        assert False, "Checkout failed — payment declined"  # ← step is marked FAILED

🧑‍💻 HTML Report Example

Open HTML Report Example


🤝 Contributing

If you have a helpful pattern or improvement to suggest:

  1. Fork the repo
  2. Create a new branch
  3. Submit a pull request

Contributions that improve report quality, add new rendering formats, or extend CI integrations are welcome.


📄 License

MIT License — see LICENSE for details.


🙏 Thanks

Thanks for exploring this repository!
Happy coding!

GitHub   PyPI   LinkedIn

GitHub   PyPI   Blog   LinkedIn

Metadata

Release files for pytest-reporter-html 2.6.0

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-reporter-html 2.6.0
File Size Uploaded Provenance Actions
pytest_reporter_html-2.6.0.tar.gz 106.7 kB Without provenance Details for pytest_reporter_html-2.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pytest-reporter-html 2.6.0
File Interpreter ABI Platform Actions
pytest_reporter_html-2.6.0-py3-none-any.whl Python 3 none any Details for pytest_reporter_html-2.6.0-py3-none-any.whl

Total release size: 133.6 kB

Release files / pytest_reporter_html-2.6.0.tar.gz

Download URL pytest_reporter_html-2.6.0.tar.gz
Size 106.7 kB
Tags Source
SHA-256 checksum
How to use checksums
1af3c75abac1a085142eec30342ae506c7130593138abf6dbfbb1b9e9bf77300
BLAKE2b-256 checksum
How to use checksums
d153ea4f1ac8a810f52208679e79321dc9275dcd749258696633f0145d9b1b06
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / pytest_reporter_html-2.6.0-py3-none-any.whl

Download URL pytest_reporter_html-2.6.0-py3-none-any.whl
Size 26.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
539f325e7ee770d47214b8eced827d9dba0247ff40829e8e8d50ff5443463264
BLAKE2b-256 checksum
How to use checksums
0851558bdc384d2cd94273c527111df8315e2ab1a03e3b5fd669a68c14c92ebf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for pytest-reporter-html 2.6.0

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