typing_checks.py
Overview
This file, `typing_checks.py`, serves as a static type-checking utility suite specifically designed to verify the correct typing behavior of various pytest-related constructs and Python typing features using **mypy**. It is **not executed at runtime** but is instead analyzed by **mypy** to ensure no typing errors arise from the usage of pytest fixtures, marks, parameterization, and related utilities.
The primary focus is on confirming the type correctness of pytest fixtures, parameterized tests, monkeypatch operations, context managers, and attributes of pytest objects such as `TestReport`. This aids in validating improvements and fixes related to typing issues documented in various pytest issues (e.g., #7488, #7494, #10999, #12941).
Contents
Imports
Standard and typing imports:
contextlib,Literal,Optional.typing_extensions.assert_type for runtime type assertions.
pytestand its componentsMonkeyPatchandTestReport.
Functions
1. check_mark_xfail_raises() -> None
Purpose:
Tests that the@pytest.mark.xfaildecorator correctly supports theraisesparameter indicating which exception is expected to cause the test to fail.Parameters: None.
Returns: None.
Behavior: Marked with
@pytest.mark.xfail(raises=RuntimeError), this test is expected to fail by raising aRuntimeError.Usage: Used as a type-checking stub to verify mypy compatibility with
xfailand itsraisesargument.
@pytest.mark.xfail(raises=RuntimeError)
def check_mark_xfail_raises() -> None:
pass
2. check_fixture_ids_callable() -> None
Purpose:
Validates that pytest fixtures can accept aparamsargument with an iterable of tuples and a callableidsfunction that takes each parameter and returns a string.Parameters: None.
Returns: None.
Behavior: Defines a fixture with
params=[(0, 0), (1, 1)]and anidslambda that converts the first element of the tuple to string.Usage: Ensures typing for fixture parameterization with callable
idsfunctions.
@pytest.fixture(params=[(0, 0), (1, 1)], ids=lambda x: str(x[0]))
def check_fixture_ids_callable() -> None:
pass
3. check_parametrize_ids_callable(func) -> None
Purpose:
Checks thatpytest.mark.parametrizecan accept a list of functions and a callableidslambda that returns the function's name.Parameters:
func: The function parameter injected by pytest parameterization (type inferred asFunctionType).
Returns: None.
Behavior: Parameterized over
[str, int]withidsgenerating the function name string.Usage: Validates typing support for
parametrizewith callableids.
@pytest.mark.parametrize("func", [str, int], ids=lambda x: str(x.__name__))
def check_parametrize_ids_callable(func) -> None:
pass
4. check_monkeypatch_typeddict(monkeypatch: MonkeyPatch) -> None
Purpose:
Tests that theMonkeyPatchfixture correctly supports operations onTypedDictinstances with typed keys.Parameters:
monkeypatch: A pytestMonkeyPatchfixture for dynamic attribute/item patching.
Returns: None.
Behavior:
Defines a
TypedDictnamedFoowith keys"x"(int) and"y"(float).Creates an instance
aofFoo.Uses
monkeypatch.setitemto change"x".Uses
monkeypatch.delitemto delete"y".
Usage: Ensures typing compatibility of monkeypatch operations on
TypedDict.
def check_monkeypatch_typeddict(monkeypatch: MonkeyPatch) -> None:
from typing import TypedDict
class Foo(TypedDict):
x: int
y: float
a: Foo = {"x": 1, "y": 3.14}
monkeypatch.setitem(a, "x", 2)
monkeypatch.delitem(a, "y")
5. check_raises_is_a_context_manager(val: bool) -> None
Purpose:
Confirms thatpytest.raises()can be used conditionally as a context manager and that the type of the context manager variable is correctly inferred.Parameters:
val: A boolean flag to decide whether to raise or not.
Returns: None.
Behavior:
Uses a conditional context manager:
pytest.raises(RuntimeError)ifvalisTrue, else a no-op context managercontextlib.nullcontext().Asserts that the type of
excinfoisOptional[pytest.ExceptionInfo[RuntimeError]].
Usage: Validates typing for conditional use of
pytest.raisesas a context manager.
def check_raises_is_a_context_manager(val: bool) -> None:
with pytest.raises(RuntimeError) if val else contextlib.nullcontext() as excinfo:
pass
assert_type(excinfo, Optional[pytest.ExceptionInfo[RuntimeError]])
6. check_testreport_attributes(report: TestReport) -> None
Purpose:
Verifies that attributes of pytest'sTestReportobject are correctly typed.Parameters:
report: An instance ofpytest.TestReport.
Returns: None.
Behavior:
Asserts that
report.whenis aLiteralof either"setup","call", or"teardown".Asserts that
report.locationis a tuple of(str, Optional[int], str).
Usage: Ensures accurate typing of
TestReportattributes to support static checking and editor autocompletion.
def check_testreport_attributes(report: TestReport) -> None:
assert_type(report.when, Literal["setup", "call", "teardown"])
assert_type(report.location, tuple[str, Optional[int], str])
Important Implementation Details
The file uses
assert_typefromtyping_extensionsto enforce and verify static types during mypy checks.It leverages pytest features such as fixtures, marks, and parameterization but does not implement actual test logic.
The conditional context manager usage (
pytest.raisesorcontextlib.nullcontext) demonstrates advanced typing scenarios with context managers and optional exception catching.The usage of
TypedDictwithin a test function shows how to patch typed dictionaries dynamically withmonkeypatch.
Interaction with Other Parts of the System
This file is tightly coupled with the pytest framework and its typing annotations.
It depends on mypy for static type validation and does not execute during normal test runs.
It validates typing related to pytest features that are used throughout the test suite in the project.
Helps maintain type safety and correctness in test code, preventing regressions introduced by changes to pytest or typing configurations.
Usage Example
Because this file is for static checking only, no runtime usage is expected. However, developers working on test suites or plugin code can refer to this file as an example of how to properly annotate and type pytest constructs with mypy.
Mermaid Diagram
flowchart TD
A[check_mark_xfail_raises()] -->|pytest.mark.xfail| B[pytest]
C[check_fixture_ids_callable()] -->|pytest.fixture with params and ids| B
D[check_parametrize_ids_callable(func)] -->|pytest.mark.parametrize with ids callable| B
E[check_monkeypatch_typeddict(monkeypatch)] -->|MonkeyPatch operations on TypedDict| B
F[check_raises_is_a_context_manager(val)] -->|Conditional pytest.raises context manager| B
G[check_testreport_attributes(report)] -->|Type assertions on TestReport| B
Summary
`typing_checks.py` is a specialized static type check file tailored for pytest-related type validation. It ensures that pytest's advanced features like marks, fixtures, parameterization, monkeypatching, and test report handling conform to expected typing standards, improving reliability and developer experience in the project's test ecosystem.