Backend Development 8 min read

Generating and Customizing pytest HTML, XML, JSON Reports with Custom Fields and Charts

This guide explains how to generate HTML, XML, and JSON reports with pytest, customize the HTML report by adding custom fields and execution time, and embed Matplotlib charts into the report, providing configuration snippets and code examples for each step.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Generating and Customizing pytest HTML, XML, JSON Reports with Custom Fields and Charts

pytest provides several reporting plugins that allow you to generate test reports in different formats such as HTML, XML, and JSON. By adding the appropriate addopts option to your pytest.ini file, you can automatically produce the desired report when running tests.

[pytest]
addopts = --html=report.html   # HTML report
addopts = --xml=report.xml     # XML report
addopts = --json=report.json   # JSON report

You can also control the verbosity of the console output with the verbosity option:

[pytest]
verbosity = 2

To add custom fields to the HTML report, the pytest-html plugin can be extended with hook functions. The example below shows how to change the report title, add a metadata field for the tester, insert an "Execution Time" column into the table header, and populate that column for each test case. It also demonstrates using the pytest_runtest_makereport hook to modify the test case name.

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

def pytest_html_report_title(report):
    report.title = "Interface Automation Test Report"

def pytest_configure(config):
    config._metadata['Tester'] = 'emily'

def pytest_html_results_table_header(cells):
    cells.insert(0, html.th('Case ID'))
    cells.insert(1, html.th('Module'))
    cells.insert(2, html.th('Case Name'))
    cells.insert(3, html.th('API Path'))
    cells.insert(5, html.th('Execution Time', class_='sortable time', col='time'))
    cells.pop(6)
    cells.pop()

def pytest_html_results_table_row(report, cells):
    url = 'http://xxx.com'
    testnode = report.nodeid.encode('utf-8').decode('unicode_escape')
    caseid = testnode.split('-')[3]
    cells.insert(0, html.td(caseid))
    module = testnode.split('-')[2]
    cells.insert(1, html.td(module))
    casename = testnode.split('-')[1]
    cells.insert(2, html.td(casename))
    cells.insert(3, html.td(url))
    cells.insert(5, html.td(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), class_='col-time'))
    cells.pop(6)
    cells.pop()

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

To embed charts in the HTML report, you can use Matplotlib to generate a PNG image during test execution and then add a new column to the report table that displays the image. The following example creates a simple line chart, saves it as chart.png , and modifies the report header and rows to include the chart.

import pytest
import matplotlib.pyplot as plt
import os

def test_sample_function():
    x = [1, 2, 3, 4, 5]
    y = [2, 4, 6, 8, 10]
    plt.plot(x, y)
    plt.xlabel('X axis')
    plt.ylabel('Y axis')
    plt.title('Chart Example')
    plt.savefig('chart.png')
    assert os.path.exists('chart.png')

def pytest_html_report_title(report):
    report.title = "Test Report"

def pytest_html_results_table_header(cells):
    cells.insert(0, html.th('Case ID'))
    cells.insert(1, html.th('Module'))
    cells.insert(2, html.th('Case Name'))
    cells.insert(3, html.th('Chart', class_='sortable chart', col='chart'))

def pytest_html_results_table_row(report, cells):
    url = 'http://xxx.com'
    testnode = report.nodeid.encode('utf-8').decode('unicode_escape')
    caseid = testnode.split('-')[3]
    cells.insert(0, html.td(caseid))
    module = testnode.split('-')[2]
    cells.insert(1, html.td(module))
    casename = testnode.split('-')[1]
    cells.insert(2, html.td(casename))
    cells.insert(3, html.td(html.Img(src='chart.png')))
    cells.pop(4)
    cells.pop()

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

After running pytest , the generated report.html will contain detailed test case information, the custom metadata fields, execution timestamps, and any embedded charts, making the report more informative for analysis and sharing.

automationhtmlpytestreportingchartsCustom Fields
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.