pytester.py

Overview

`pytester.py` provides a rich set of tools, fixtures, and helper classes designed to facilitate testing of **pytest itself** and **pytest plugins**. It offers an isolated environment for running pytest test runs—either in-process or subprocess—enabling black-box style testing of pytest features, plugins, and configurations. This module provides mechanisms to create test files and directories, run pytest with various options, capture and analyze output, and introspect hook calls and test reports.

Key functionalities include:

This file is a core utility in the pytest testing ecosystem, enabling pytest's own tests and plugin authors to verify pytest behavior reliably.


Detailed Documentation

Module-level Functions

pytest_addoption(parser: Parser) -> None

Adds command-line options and ini settings related to the pytester utilities:


pytest_configure(config: Config) -> None

Configures the pytester plugin, registering [LsofFdLeakChecker](/projects/286/67442) if needed, and adds a marker [pytester_example_path](/projects/286/67470) to help locate test example files.


Class: LsofFdLeakChecker

A platform-specific file descriptor leak checker using `lsof`. It runs before and after each test to detect leaked file descriptors.


Fixture: _pytest

Returns a [PytestArg](/projects/286/67266) helper, which exposes a [gethookrecorder()](/projects/286/67271) method to capture hook calls during pytest runs.


Class: PytestArg

Helper class returned by `_pytest` fixture.


Utility Function: get_public_names(values: Iterable[str]) -> list[str]

Filters an iterable of names and returns only those that do not start with an underscore (public names).


Class: RecordedHookCall

Represents a single recorded hook call, storing the name of the hook and its keyword arguments as attributes.

Usage example:

calls = hook_recorder.getcalls("pytest_runtest_setup")
assert calls[0].item is an_item

Class: HookRecorder

Records all hook calls made by a `PytestPluginManager` and provides utilities to query and assert them.


Fixtures: linecomp, LineMatcher


Class: RunResult

Encapsulates the result of running a pytest command or subprocess.


Classes: SysModulesSnapshot, SysPathsSnapshot

Snapshot and restore the state of `sys.modules` and `sys.path` respectively to isolate test runs and prevent pollution between tests.


Class: Pytester

The central class of this module, providing comprehensive facilities for pytest plugin and pytest core testing.

**Key features:**

**Initialization:**

Pytester(
    request: FixtureRequest,
    tmp_path_factory: TempPathFactory,
    monkeypatch: MonkeyPatch,
    *,
    _ispytest: bool = False,
)

**Important properties and methods:**


Class: LineComp

Helper class wrapping a `StringIO` used to assert that the stream contains lines in a linear sequence.


Class: LineMatcher

Utility class for flexible line-by-line matching of text output using glob (`fnmatch`) or regex.


Implementation Details and Algorithms


Interaction with Other Parts of the System


Visual Diagram: Class Diagram

classDiagram
    class Pytester {
        +path: Path
        +makefile(ext, *args, **kwargs) Path
        +makepyfile(*args, **kwargs) Path
        +makeconftest(source) Path
        +makeini(source) Path
        +getnode(config, arg) Collector|Item
        +getitem(source, funcname) Item
        +runpytest(*args, **kwargs) RunResult
        +inline_run(*args, plugins=(), no_reraise_ctrlc=False) HookRecorder
        +runpython(script) RunResult
        +spawn(cmd, expect_timeout=10.0) pexpect.spawn
        +mkdir(name) Path
        +mkpydir(name) Path
        +copy_example(name) Path
    }

    class HookRecorder {
        +calls: list[RecordedHookCall]
        +getcalls(names) list[RecordedHookCall]
        +assert_contains(entries)
        +popcall(name) RecordedHookCall
        +getcall(name) RecordedHookCall
        +getreports(names) list
        +getfailures(names) list
        +assertoutcome(passed, skipped, failed)
    }

    class RecordedHookCall {
        +_name: str
        +__repr__()
    }

    class RunResult {
        +ret: ExitCode|int
        +outlines: list[str]
        +errlines: list[str]
        +stdout: LineMatcher
        +stderr: LineMatcher
        +duration: float
        +parseoutcomes() dict
        +assert_outcomes(...)
    }

    class LineMatcher {
        +lines: list[str]
        +fnmatch_lines(lines2, consecutive=False)
        +re_match_lines(lines2, consecutive=False)
        +no_fnmatch_line(pat)
        +no_re_match_line(pat)
    }

    Pytester --> HookRecorder : creates
    HookRecorder --> RecordedHookCall : records
    Pytester --> RunResult : returns results
    RunResult --> LineMatcher : stdout, stderr

Usage Examples

Example: Creating a Python file and running pytest inline

def test_example(pytester):
    pytester.makepyfile("""
        def test_always_passes():
            assert True
    """)
    result = pytester.runpytest()
    result.stdout.fnmatch_lines(["*1 passed*"])

Example: Using HookRecorder to assert hook calls

def test_hook_calls(_pytest):
    hookrec = _pytest.gethookrecorder(pytester_hook)
    # run some pytest actions
    calls = hookrec.getcalls("pytest_runtest_setup")
    assert calls
    assert hasattr(calls[0], "item")

Example: Using LineMatcher for output assertions

def test_output_matching():
    output_lines = [
        "Starting tests",
        "test_foo.py::test_bar PASSED",
        "=== 1 passed in 0.01s ==="
    ]
    matcher = LineMatcher(output_lines)
    matcher.fnmatch_lines([
        "test_foo.py::* PASSED",
        "*1 passed*"
    ])

Summary

`pytester.py` is a comprehensive testing utility module designed to facilitate testing pytest itself and pytest plugins by providing an isolated environment, file management, process running capabilities, detailed hook recording, and output assertion helpers. Its core class `Pytester` along with `HookRecorder`, `RunResult`, and `LineMatcher` provide a powerful toolkit for black-box and white-box testing of pytest behavior. This module integrates deeply with pytest internals and external tools to achieve reliable and reproducible test environments.


End of Documentation for pytester.py