junitxml.py


Overview

The [junitxml.py](/projects/286/67489) file is a pytest plugin module responsible for generating test reports in the **JUnit XML format**. This format is widely used by continuous integration (CI) systems like Jenkins, CircleCI, and others to consume and display test results. The module listens to pytest test lifecycle events, collects detailed information about each test's execution outcome (pass, fail, skip, error), and constructs a well-formed XML document that conforms to JUnit XML schemas (`legacy`, `xunit1`, `xunit2`).

Key features include:

This module complements pytest’s test execution and terminal reporting by providing an extensible, standardized XML output format for automated test result processing.


Detailed Explanation of Classes, Functions, and Methods

Functions


bin_xml_escape(arg: object) -> str

Visually escapes characters in strings that are invalid in XML, replacing them with a visible `#xXX` hexadecimal notation. This is not a true XML escape (no ampersand prefix) but is intended to make illegal characters visible in XML output.


merge_family(left, right) -> None

Merges two dictionaries representing attribute "families" for different JUnit XML schema variants by concatenating their attribute lists.


mangle_test_address(address: str) -> list[str]

Transforms a pytest node ID (test address) into a list of strings representing the test "classname" and "name". It converts file paths to dotted module notation and preserves parameterized test suffixes.


_warn_incompatibility_with_xunit2(request: FixtureRequest, fixture_name: str) -> None

Issues a pytest warning if a fixture is used that is incompatible with the newer `xunit2` JUnit family schemas.


Fixtures


record_property(request: FixtureRequest) -> Callable[[str, object], None]

A pytest fixture that allows tests to add additional `` elements to the test’s JUnit XML report.


record_xml_attribute(request: FixtureRequest) -> Callable[[str, object], None]

Fixture for adding extra XML attributes directly to the test case element in the JUnit XML output.


record_testsuite_property(request: FixtureRequest) -> Callable[[str, object], None]

Session-scoped fixture to add global `` tags to the root `` element, suitable for adding metadata about the entire test session.


Class _NodeReporter

Internal helper class representing a single test case’s XML node and its associated data.

Initialization

_NodeReporter(nodeid: str | TestReport, xml: LogXML)

Properties

Methods


Class LogXML

Core class managing the entire JUnit XML report lifecycle and integration with pytest hooks.

Initialization

LogXML(
    logfile,
    prefix: str | None,
    suite_name: str = "pytest",
    logging: str = "no",
    report_duration: str = "total",
    family="xunit1",
    log_passing_tests: bool = True,
)

Key Properties

Key Methods


pytest Hooks and Configuration Integration


Important Implementation Details and Algorithms


Interaction with Other Parts of the System


Usage Example

Add the following option when running pytest to generate a JUnit XML report:

pytest --junitxml=results.xml

Inside a test, add custom properties:

def test_example(record_property):
    record_property("priority", "high")
    assert 1 == 1

The generated `results.xml` will contain `` inside the corresponding `` element.


Visual Diagram

classDiagram
    class LogXML {
        +__init__(logfile, prefix, suite_name, logging, report_duration, family, log_passing_tests)
        +pytest_runtest_logreport(report)
        +pytest_collectreport(report)
        +pytest_internalerror(excrepr)
        +pytest_sessionstart()
        +pytest_sessionfinish()
        +pytest_terminal_summary(terminalreporter)
        +node_reporter(report)
        +add_stats(key)
        +update_testcase_duration(report)
        +add_global_property(name, value)
        -_get_global_properties_node()
    }
    class _NodeReporter {
        +__init__(nodeid, xml)
        +append(node)
        +add_property(name, value)
        +add_attribute(name, value)
        +make_properties_node()
        +record_testreport(testreport)
        +to_xml()
        +_add_simple(tag, message, data)
        +write_captured_output(report)
        +append_pass(report)
        +append_failure(report)
        +append_collect_error(report)
        +append_collect_skipped(report)
        +append_error(report)
        +append_skipped(report)
        +finalize()
    }
    LogXML "1" o-- "*" _NodeReporter : manages

Summary

[junitxml.py](/projects/286/67489) is a pytest plugin module that generates JUnit-compatible XML reports for test results, providing rich metadata about test execution including outcome, duration, captured output, and custom user properties. Its robust design supports multiple XML schema versions, handles complex test lifecycle scenarios including parallel execution, and integrates seamlessly into pytest’s plugin and fixture systems. This enables integration with CI pipelines and other tools that consume JUnit XML, making it an essential component for automated testing ecosystems.