reports.py
Overview
The `reports.py` file defines core data structures and serialization logic for test reports within the testing framework. It encapsulates detailed information about individual test outcomes and collection results, including their status, timing, captured output, and exception information.
This file provides:
Base and specialized report classes (
BaseReport,TestReport,CollectReport) that represent the results of test execution and collection respectively.Methods to serialize/deserialize these reports for inter-process communication or persistence.
Utilities for formatting and displaying reports in terminal output.
Integration hooks for pytest’s reporting plugin system.
These reports serve as the fundamental data units communicated between test execution, reporting subsystems (e.g., terminal output, JUnit XML generation), and plugins.
Classes and Functions
getworkerinfoline(node)
Fetches and caches a formatted string representing worker information (usually for distributed test execution contexts) attached to a pytest node.
Parameters:
node: A pytest node object, expected to have aworkerinfoattribute.
Returns:
A string summary like "[gw0] linux -- Python 3.8.5 /usr/bin/python3" or cached value.
**Usage example:**
worker_line = getworkerinfoline(test_node)
print(worker_line)
class BaseReport
Base class representing the outcome of a test phase or collection step. This class is extended by specialized reports.
**Attributes:**
when: str | None— Phase of test execution ("setup","call","teardown"), or"collect"for collection reports.location: tuple[str, int | None, str] | None— Location info(filepath, lineno, domain).longrepr— Failure or error representation; can be various types (string, exception info, terminal repr).sections: list[tuple[str, str]]— Sections of captured output or logs.nodeid: str— Unique test identifier.outcome: Literal["passed", "failed", "skipped"]— Test outcome.
**Key Methods and Properties:**
__init__(**kw: Any): Initializes report attributes with passed keyword arguments.toterminal(out: TerminalWriter): Writes the longrepr of the report to a terminal output stream.get_sections(prefix: str) -> Iterator[tuple[str, str]]: Yield sections whose names start withprefix.longreprtext(property): Returns the full string representation oflongrepr.caplog,capstdout,capstderr(properties): Return captured log, stdout, and stderr output respectively.passed,failed,skipped(properties): Boolean flags for outcome.fspath(property): File system path portion ofnodeid.count_towards_summary(property): Experimental flag whether this report counts in summary statistics.head_line(property): Experimental "head line" used in traceback output._get_verbose_word_with_markup(config, default_markup): Helper to get verbose status word with markup from config hooks._to_json() -> dict[str, Any]: Serialize the report to a JSON-serializable dict._from_json(reportdict: dict[str, object]) -> Self: Deserialize JSON dict back into a report instance.
class TestReport(BaseReport)
Specialized report representing the result of running a test phase (`setup`, `call`, or `teardown`).
**Additional Attributes:**
keywords: Mapping[str, Any]— Markers or keywords associated with the test.user_properties: list[tuple[str, object]]— User-defined test properties.duration: float— Duration of the test phase in seconds.start: float— Start timestamp (epoch seconds).stop: float— Stop timestamp (epoch seconds).wasxfail: str(optional) — Reason string if test was expected to fail (xfail).
**Constructor Parameters:**
def __init__(
self,
nodeid: str,
location: tuple[str, int | None, str],
keywords: Mapping[str, Any],
outcome: Literal["passed", "failed", "skipped"],
longrepr: None | ExceptionInfo[BaseException] | tuple[str, int, str] | str | TerminalRepr,
when: Literal["setup", "call", "teardown"],
sections: Iterable[tuple[str, str]] = (),
duration: float = 0,
start: float = 0,
stop: float = 0,
user_properties: Iterable[tuple[str, object]] | None = None,
**extra,
) -> None
**Notable Methods:**
from_item_and_call(item: Item, call: CallInfo[None]) -> TestReport:
Factory method to create aTestReportfrom a pytestItemand aCallInfoobject representing a test phase call.
**Usage example:**
report = TestReport.from_item_and_call(test_item, callinfo)
print(report.outcome)
print(report.duration)
class CollectReport(BaseReport)
Report representing the outcome of a test collection phase.
**Attributes:**
result: list[Item | Collector] | None— List of collected items and collectors.when: Literal["collect"]— Fixed to"collect".
**Constructor Parameters:**
def __init__(
self,
nodeid: str,
outcome: Literal["passed", "failed", "skipped"],
longrepr: None | ExceptionInfo[BaseException] | tuple[str, int, str] | str | TerminalRepr,
result: list[Item | Collector] | None,
sections: Iterable[tuple[str, str]] = (),
**extra,
) -> None
**Usage example:**
collect_report = CollectReport(nodeid="tests/test_module.py", outcome="passed", longrepr=None, result=collected_items)
class CollectErrorRepr(TerminalRepr)
Simple terminal representation of a collection error message.
Attributes:
longrepr: str— The error message.
Methods:
toterminal(out: TerminalWriter): Writes the error message to terminal, styled in red.
Serialization Functions
These functions support converting reports to/from JSON-serializable dictionaries for inter-process communication or persistence.
pytest_report_to_serializable(report: CollectReport | TestReport) -> dict[str, Any] | None
Converts a report instance to a serializable dict, adding a$report_typekey.pytest_report_from_serializable(data: dict[str, Any]) -> CollectReport | TestReport | None
Creates a report instance from serialized data._report_to_json(report: BaseReport) -> dict[str, Any]
Internal helper to serialize a report, including complex nested exception representation._report_kwargs_from_json(reportdict: dict[str, Any]) -> dict[str, Any]
Internal helper to deserialize report dictionaries back into constructor kwargs._report_unserialization_failure(type_name: str, report_class: type[BaseReport], reportdict) -> NoReturn
Helper to raise a runtime error on unknown deserialization data.
Important Implementation Details
Exception Representation Serialization:
Thelongreprattribute may contain complex nested exception representations (ExceptionChainRepr,ReprExceptionInfo, etc). The serialization logic carefully serializes nested data classes likeReprTraceback,ReprEntry, andReprFileLocationinto dictionaries.Flexible
longreprTypes:longreprcan beNone, strings, tuples(file, line, message), or rich terminal representations. Thetoterminalmethod handles these polymorphically.Caching Worker Info:
Thegetworkerinfolinefunction caches formatted worker info on the node to avoid recomputation.Experimental API:
Properties likecount_towards_summaryandhead_lineare marked experimental and may change.Use of
@final:TestReportandCollectReportclasses are marked@finalto discourage subclassing.Rich Capture Sections:
Reports store arbitrarysections(name-content pairs) which can include captured stdout, stderr, and logs, accessible via dedicated properties.
Interaction With Other System Components
Test Execution (
_pytest.runner):TestReportinstances are commonly created by the test execution engine after running setup/call/teardown phases.Collection (
_pytest.nodes):CollectReportinstances represent the result of test collection phases, including gatheredItemandCollectorobjects.Terminal Reporting (
_pytest.terminal):
Reports provide thetoterminalmethod used by terminal reporters to render detailed failure or skip information.Inter-Process Communication:
Serialization methods enable sending reports between pytest workers and the main process in distributed or parallel test execution scenarios.Plugins and Hooks:
Plugins hook on pytest reporting events (pytest_runtest_logreport) and consumeTestReport/CollectReportobjects.
Visual Diagram: Class Structure of reports.py
classDiagram
class BaseReport {
+str when
+tuple location
+longrepr
+list~tuple~sections~
+str nodeid
+str outcome
+__init__(**kw)
+toterminal(out: TerminalWriter)
+get_sections(prefix: str)
+longreprtext
+caplog
+capstdout
+capstderr
+passed
+failed
+skipped
+fspath
+count_towards_summary
+head_line
+_get_verbose_word_with_markup(config, default_markup)
+_to_json() dict
+_from_json(reportdict) Self
}
class TestReport {
+str nodeid
+tuple location
+Mapping keywords
+str outcome
+longrepr
+str when
+list sections
+float duration
+float start
+float stop
+list user_properties
+wasxfail
+__init__(...)
+from_item_and_call(item, call) TestReport
+__repr__()
}
class CollectReport {
+str nodeid
+str outcome
+longrepr
+list result
+list sections
+when = "collect"
+__init__(...)
+location property
+__repr__()
}
class CollectErrorRepr {
+str longrepr
+__init__(msg)
+toterminal(out: TerminalWriter)
}
BaseReport <|-- TestReport
BaseReport <|-- CollectReport
TerminalRepr <|-- CollectErrorRepr
Summary
`reports.py` is a foundational module defining how test results and collection data are represented, serialized, and displayed within the testing framework. The `BaseReport` class encapsulates common report behavior, while `TestReport` and `CollectReport` specialize for test execution phases and collection respectively. Serialization helpers enable inter-process communication, crucial for distributed test runs.
This module closely interacts with the test execution engine, terminal reporters, and plugins, serving as the canonical source of truth for test outcomes and their rich contextual data.