Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use pytest-html’s report.extras to attach selected per-test artifacts, pytest’s built-in capture for ordinary failure output and logs, and pytest-metadata’s hooks to populate the report’s Environment table. Screenshots must come from your browser or application fixture: pytest-html formats an image or file/link reference but does not control the test driver or take screenshots for you.

Generate a pytest-HTML report

Install pytest-html in the test environment, then run pytest with the desired output file:

pytest --html=report.html

By default, report assets such as CSS and images are stored separately. To request one HTML file, add --self-contained-html:

pytest --html=report.html --self-contained-html

A self-contained report does not guarantee that images referenced by a file path or URL are embedded. Those references may still depend on external files or network resources, and can break when the report is moved. The pytest-html user guide documents this limitation; choose an attachment form that suits how the report will be shared, and verify it in your own workflow.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Attach screenshots and selected per-test details

Use the pytest_runtest_makereport hook wrapper to add extras after pytest creates a report for a test phase. The example below attaches a screenshot and selected diagnostic text only when the test call fails or is skipped:

import pytest
import pytest_html


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()
    extras = getattr(report, "extras", [])

    if report.when == "call" and (report.failed or report.skipped):
        # Your fixture or plugin must make this path available.
        screenshot_path = getattr(item, "screenshot_path", None)
        if screenshot_path:
            extras.append(
                pytest_html.extras.image(screenshot_path, name="Screenshot")
            )

        extras.append(
            pytest_html.extras.text(
                "Selected diagnostic detail", name="Diagnostic detail"
            )
        )

    report.extras = extras

This is a hook pattern, not a ready-made Selenium, Playwright, or other browser integration. Your test setup must capture the screenshot at a useful point and make its path or image data available. This example filters to the call phase; remove or adjust that condition if setup or teardown failures also need artifacts. The official guide’s example also considers outcomes such as xfail, so align the conditions with the reports your team wants to annotate.

Choose an image representation

The extras API provides helpers for images and other content, including HTML, JSON, text, URL, PNG, JPEG, and SVG. An image extra can display image content; a file or URL extra references an external resource. The choice affects portability and report size: inline content can travel with the report but increases its size, while references can keep the report lighter but require the referenced file or URL to remain available. Self-contained HTML does not turn every external reference into embedded content.

Use the extras fixture when the test owns the artifact

If a test naturally creates its own content, the extras fixture can append it without a report hook. Use a hook for cross-cutting behavior, such as adding screenshots to qualifying failures across the suite. Fixture-provided extras generally appear before extras added by plugins. New code should use the plural extras API; pytest-html deprecated report.extra and the singular extra fixture in version 4.0.0. See the pytest-html deprecations.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Include logs without duplicating all test output

Pytest already captures standard output, standard error, and logs at WARNING level or higher by default. For failed tests, captured output and logs are shown in the test report, so a custom attachment hook is not needed just to make ordinary failure capture available. The pytest logging guide describes capture behavior and the caplog fixture.

Use caplog inside a test when you need to inspect log records or formatted log text, or deliberately attach a smaller diagnostic extract as pytest_html.extras.text(...) or pytest_html.extras.json(...). This makes the selected content explicit rather than exposing all captured output. Do not assume a caplog value is automatically available on the report object inside a hook; if the test must pass data to a hook, implement and clean up that transfer in project-specific code.

If your logging setup uses dictConfig or otherwise replaces root logger configuration, it may remove the handler that caplog relies on. Preserve existing handlers where appropriate and verify capture with your project’s logging configuration.

Populate the Environment table

pytest-html’s Environment table is provided by the pytest-metadata plugin. Add values available before tests begin in pytest_configure using the plugin’s metadata stash key:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from pytest_metadata.plugin import metadata_key


def pytest_configure(config):
    config.stash[metadata_key]["Build"] = "staging"
    config.stash[metadata_key]["Python version"] = "3.x"

For values known only when the test session finishes, update the same stash in pytest_sessionfinish:

import pytest
from pytest_metadata.plugin import metadata_key


@pytest.hookimpl(tryfirst=True)
def pytest_sessionfinish(session, exitstatus):
    session.config.stash[metadata_key]["Build"] = "staging"

tryfirst=True gives the hook a best-effort chance to run before pytest-html and pytest-metadata finalize the Environment table. Environment entries are alphabetically sorted unless the metadata is a collections.OrderedDict. See the pytest-html user guide for the documented hooks and metadata behavior.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Redact sensitive values before sharing

Configure environment_table_redact_list in pytest configuration to gray out matching environment variable values in the Environment table; the variable names remain visible. The setting accepts regular expressions:

[pytest]
environment_table_redact_list = ^API_TOKEN$
    .*PASSWORD.*
    .*SECRET.*

This protects matching values in the metadata table, not every place a secret could appear. Review screenshots, attached text, logs, and HTML extras separately before sharing a report.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose what to attach

Need Use Trade-off
Ordinary stdout, stderr, and warning-or-higher logs for failures Pytest’s built-in capture Available in failure output without a custom attachment; includes captured test output rather than only a hand-picked excerpt.
A deliberately selected log or diagnostic excerpt Collect it in the test and attach as text or JSON Controls what the report exposes, but requires project code to select and supply the content.
An image that should travel as report content An image extra with image content Can improve portability but increases report size; check how your chosen content is rendered.
A screenshot stored elsewhere A file or URL reference extra Keeps the report dependent on the referenced path or URL; the reference is not guaranteed to be embedded by self-contained HTML.

The screenshot capture mechanism and the report’s portability depend on your test driver, attachment representation, and sharing workflow; validate those details in your project.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.