Skip to content

Latest commit

 

History

History
322 lines (221 loc) · 10.2 KB

README.rst

File metadata and controls

322 lines (221 loc) · 10.2 KB

pytest-html

pytest-html is a plugin for pytest that generates a HTML report for the test results.

License PyPI Conda Forge CI Requirements Codecov

Requirements

You will need the following prerequisites in order to use pytest-html:

  • Python 3.6+ or PyPy3

Installation

To install pytest-html:

$ pip install pytest-html

Then run your tests with:

$ pytest --html=report.html

ANSI codes

Note that ANSI code support depends on the ansi2html package. Due to the use of a less permissive license, this package is not included as a dependency. If you have this package installed, then ANSI codes will be converted to HTML in your report.

Creating a self-contained report

In order to respect the Content Security Policy (CSP), several assets such as CSS and images are stored separately by default. You can alternatively create a self-contained report, which can be more convenient when sharing your results. This can be done in the following way:

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

Images added as files or links are going to be linked as external resources, meaning that the standalone report HTML-file may not display these images as expected.

The plugin will issue a warning when adding files or links to the standalone report.

Enhancing reports

Appearance

Custom CSS (Cascasding Style Sheets) can be passed on the command line using the --css option. These will be applied in the order specified, and can be used to change the appearance of the report.

$ pytest --html=report.html --css=highcontrast.css --css=accessible.css

Report Title

By default report title will be the filename of the report, you can edit it by using the pytest_html_report_title hook:

def pytest_html_report_title(report):
    report.title = "My very own title!"

Environment

The Environment section is provided by the pytest-metadata plugin, and can be accessed via the pytest_configure hook:

def pytest_configure(config):
    config._metadata["foo"] = "bar"

The generated table will be sorted alphabetically unless the metadata is a collections.OrderedDict.

Additional summary information

You can edit the Summary section by using the pytest_html_results_summary hook:

from py.xml import html


def pytest_html_results_summary(prefix, summary, postfix):
    prefix.extend([html.p("foo: bar")])

Extra content

You can add details to the HTML reports by creating an 'extra' list on the report object. Here are the types of extra content that can be added:

Type Example
Raw HTML extra.html('<div>Additional HTML</div>')
JSON extra.json({'name': 'pytest'})
Plain text extra.text('Add some simple Text')
URL extra.url('http://www.example.com/')
Image extra.image(image, mime_type='image/gif', extension='gif')
Image extra.image('/path/to/file.png')
Image extra.image('http://some_image.png')

Note: When adding an image from file, the path can be either absolute or relative.

Note: When using --self-contained-html, images added as files or links may not work as expected, see section Creating a self-contained report for more info.

There are also convenient types for several image formats:

Image format Example
PNG extra.png(image)
JPEG extra.jpg(image)
SVG extra.svg(image)

The following example adds the various types of extras using a pytest_runtest_makereport hook, which can be implemented in a plugin or conftest.py file:

import pytest


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    pytest_html = item.config.pluginmanager.getplugin("html")
    outcome = yield
    report = outcome.get_result()
    extra = getattr(report, "extra", [])
    if report.when == "call":
        # always add url to report
        extra.append(pytest_html.extras.url("http://www.example.com/"))
        xfail = hasattr(report, "wasxfail")
        if (report.skipped and xfail) or (report.failed and not xfail):
            # only add additional html on failure
            extra.append(pytest_html.extras.html("<div>Additional HTML</div>"))
        report.extra = extra

You can also specify the name argument for all types other than html which will change the title of the created hyper link:

extra.append(pytest_html.extras.text("some string", name="Different title"))

It is also possible to use the fixture extra to add content directly in a test function without implementing hooks. These will generally end up before any extras added by plugins.

from pytest_html import extras


def test_extra(extra):
    extra.append(extras.text("some string"))

Modifying the results table

You can modify the columns by implementing custom hooks for the header and rows. The following example conftest.py adds a description column with the test function docstring, adds a sortable time column, and removes the links column:

from datetime import datetime
from py.xml import html
import pytest


def pytest_html_results_table_header(cells):
    cells.insert(2, html.th("Description"))
    cells.insert(1, html.th("Time", class_="sortable time", col="time"))
    cells.pop()


def pytest_html_results_table_row(report, cells):
    cells.insert(2, html.td(report.description))
    cells.insert(1, html.td(datetime.utcnow(), class_="col-time"))
    cells.pop()


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()
    report.description = str(item.function.__doc__)

You can also remove results by implementing the pytest_html_results_table_row hook and removing all cells. The following example removes all passed results from the report:

def pytest_html_results_table_row(report, cells):
    if report.passed:
        del cells[:]

The log output and additional HTML can be modified by implementing the pytest_html_results_html hook. The following example replaces all additional HTML and log output with a notice that the log is empty:

from py.xml import html


def pytest_html_results_table_html(report, data):
    if report.passed:
        del data[:]
        data.append(html.div("No log output captured.", class_="empty log"))

Display options

By default, all rows in the Results table will be expanded except those that have Passed.

This behavior can be customized either with a query parameter: ?collapsed=Passed,XFailed,Skipped or by setting the render_collapsed in a configuration file (pytest.ini, setup.cfg, etc).

[pytest]
render_collapsed = True

NOTE: Setting render_collapsed will, unlike the query parameter, affect all statuses.

The formatting of the timestamp used in the Durations column can be modified by setting duration_formatter on the report attribute. All time.strftime formatting directives are supported. In addition, it is possible to supply %f to get duration milliseconds. If this value is not set, the values in the Durations column are displayed in %S.%f format where %S is the total number of seconds a test ran for.

Below is an example of a conftest.py file setting duration_formatter:

import pytest


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()
    setattr(report, "duration_formatter", "%H:%M:%S.%f")

NOTE: Milliseconds are always displayed with a precision of 2

Screenshots

Enhanced HTML report

Contributing

We welcome contributions.

To learn more, see Development

Resources