Skip to content

Commit ca35145

Browse files
mwychungnicoddemus
andauthored
Added dedicated page about using types with pytest #12842 (#12963)
Fixes #12842 --------- Co-authored-by: Bruno Oliveira <bruno@pytest.org>
1 parent d3adf46 commit ca35145

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ lovetheguitar
265265
Lukas Bednar
266266
Luke Murphy
267267
Maciek Fijalkowski
268+
Maggie Chung
268269
Maho
269270
Maik Figura
270271
Mandeep Bhutani

changelog/12842.doc.rst

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added dedicated page about using types with pytest.
2+
3+
See :ref:`types` for detailed usage.

doc/en/explanation/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ Explanation
1212
fixtures
1313
goodpractices
1414
pythonpath
15+
types
1516
ci
1617
flaky

doc/en/explanation/types.rst

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
.. _types:
2+
3+
Typing in pytest
4+
================
5+
6+
.. note::
7+
This page assumes the reader is familiar with Python's typing system and its advantages.
8+
9+
For more information, refer to `Python's Typing Documentation <https://docs.python.org/3/library/typing.html>`_.
10+
11+
Why type tests?
12+
---------------
13+
14+
Typing tests provides significant advantages:
15+
16+
- **Readability:** Clearly defines expected inputs and outputs, improving readability, especially in complex or parameterized tests.
17+
18+
- **Refactoring:** This is the main benefit in typing tests, as it will greatly help with refactoring, letting the type checker point out the necessary changes in both production and tests, without needing to run the full test suite.
19+
20+
For production code, typing also helps catching some bugs that might not be caught by tests at all (regardless of coverage), for example:
21+
22+
.. code-block:: python
23+
24+
def get_caption(target: int, items: list[tuple[int, str]]) -> str:
25+
for value, caption in items:
26+
if value == target:
27+
return caption
28+
29+
30+
The type checker will correctly error out that the function might return `None`, however even a full coverage test suite might miss that case:
31+
32+
.. code-block:: python
33+
34+
def test_get_caption() -> None:
35+
assert get_caption(10, [(1, "foo"), (10, "bar")]) == "bar"
36+
37+
38+
Note the code above has 100% coverage, but the bug is not caught (of course the example is "obvious", but serves to illustrate the point).
39+
40+
41+
42+
Using typing in test suites
43+
---------------------------
44+
45+
To type fixtures in pytest, just add normal types to the fixture functions -- there is nothing special that needs to be done just because of the `fixture` decorator.
46+
47+
.. code-block:: python
48+
49+
import pytest
50+
51+
52+
@pytest.fixture
53+
def sample_fixture() -> int:
54+
return 38
55+
56+
In the same manner, the fixtures passed to test functions need be annotated with the fixture's return type:
57+
58+
.. code-block:: python
59+
60+
def test_sample_fixture(sample_fixture: int) -> None:
61+
assert sample_fixture == 38
62+
63+
From the POV of the type checker, it does not matter that `sample_fixture` is actually a fixture managed by pytest, all it matters to it is that `sample_fixture` is a parameter of type `int`.
64+
65+
66+
The same logic applies to :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>`:
67+
68+
.. code-block:: python
69+
70+
71+
@pytest.mark.parametrize("input_value, expected_output", [(1, 2), (5, 6), (10, 11)])
72+
def test_increment(input_value: int, expected_output: int) -> None:
73+
assert input_value + 1 == expected_output
74+
75+
76+
The same logic applies when typing fixture functions which receive other fixtures:
77+
78+
.. code-block:: python
79+
80+
@pytest.fixture
81+
def mock_env_user(monkeypatch: pytest.MonkeyPatch) -> None:
82+
monkeypatch.setenv("USER", "TestingUser")
83+
84+
85+
Conclusion
86+
----------
87+
88+
Incorporating typing into pytest tests enhances **clarity**, improves **debugging** and **maintenance**, and ensures **type safety**.
89+
These practices lead to a **robust**, **readable**, and **easily maintainable** test suite that is better equipped to handle future changes with minimal risk of errors.

0 commit comments

Comments
 (0)