pytest-html
pytest-html is a plugin for pytest that generates a HTML report for the test results.
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-htmlThen run your tests with:
$ pytest --html=report.htmlANSI 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-htmlImages 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.cssReport Title
By default report title will be the filename of the report, you can edit it by using the :code: pytest_html_report_title hook:
import pytest
from py.xml import html
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:
import pytest
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 = extraYou 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:
import pytest
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:
import pytest
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 = TrueNOTE: Setting render_collapsed will, unlike the query parameter, affect all statuses.
Screenshots
Contributing
We welcome contributions.
To learn more, see Development