|
| 1 | +.. _types: |
| 2 | + |
| 3 | +How to use Types with Pytest |
| 4 | +=========================================== |
| 5 | + |
| 6 | +You can add typing in pytest functions that helps to specify what type of data a function expects and returns. |
| 7 | +This guide explains how to apply typing in pytest to improve code readability and prevent type-related errors. |
| 8 | + |
| 9 | + |
| 10 | +1. Introduction to Typing |
| 11 | +----------------- |
| 12 | + |
| 13 | +Typing in Python helps developers specify the expected data types of variables, function parameters, and return values. |
| 14 | +It improves code clarity and prevents type errors. |
| 15 | + |
| 16 | +For example: |
| 17 | + |
| 18 | + |
| 19 | +.. code-block:: python |
| 20 | + def add(x: int, y: int) -> int: |
| 21 | + return x + y |
| 22 | +
|
| 23 | +In this example: |
| 24 | +`x: int` and `y: int` mean that `x` and `y` should be integers. |
| 25 | +`-> int` shows that the function returns an integer. |
| 26 | + |
| 27 | +It makes the intentions clear that both the input and output are expected to be integers. |
| 28 | + |
| 29 | +2. Typing Test Functions |
| 30 | +----------------- |
| 31 | +Test functions in pytest check whether the code runs correctly. |
| 32 | +While test functions do not return values, we can add `-> None` as the return type. |
| 33 | + |
| 34 | +For example: |
| 35 | + |
| 36 | +.. code-block:: python |
| 37 | + import pytest |
| 38 | +
|
| 39 | +
|
| 40 | + def test_add() -> None: |
| 41 | + result = add(2, 3) |
| 42 | + assert result == 5 |
| 43 | +
|
| 44 | +In this function: |
| 45 | +`test_add` is typed as `-> None` because it does not return anything. |
| 46 | +The assertion `assert result == 5` checks if the result is correct. |
| 47 | + |
| 48 | +Example result: |
| 49 | +If the input data type is incorrect, like passing `add("2", 3)`, a `TypeError` will occur. |
| 50 | + |
| 51 | +3. Typing Fixtures |
| 52 | +----------------- |
| 53 | +Fixtures in pytest helps set up data or provides resources needed for tests. |
| 54 | +Adding type hints helps clarify what kind of data the fixtures returns, making code easier to read and easier to debug. |
| 55 | + |
| 56 | +* Basic Fixture Typing: |
| 57 | + |
| 58 | +If a fixture returns a number, you can specify it returns an `int`: |
| 59 | + |
| 60 | +.. code-block:: python |
| 61 | + import pytest |
| 62 | +
|
| 63 | +
|
| 64 | + @pytest.fixture |
| 65 | + def sample_fixture() -> int: |
| 66 | + return 38 |
| 67 | +
|
| 68 | +
|
| 69 | + def test_sample_fixture(sample_fixture: int) -> None: |
| 70 | + assert sample_fixture == 38 |
| 71 | +
|
| 72 | +In this example: |
| 73 | +`sample_fixture()` is typed to return an `int`. |
| 74 | +In `test_sample_fixture`, using typing with fixtures, it ensures the return is an integer. |
| 75 | +If you change the return from an integer to a string (``"42"``), the test will fail. |
| 76 | + |
| 77 | + |
| 78 | +* Typing Fixtures with Lists and Dictionaries: |
| 79 | +Here are the examples showing how to use List and Dict types in pytest. |
| 80 | +When you want to use complex data structures like lists or dictionaries, import `List` and `Dict` from Python's `typing` module to specify the types. |
| 81 | +Note: From Python 3.5 or later, typing module is built-in module in Python. |
| 82 | + |
| 83 | + |
| 84 | +.. code-block:: python |
| 85 | + from typing import List |
| 86 | + import pytest |
| 87 | +
|
| 88 | +
|
| 89 | + # Fixture returning a list of integers |
| 90 | + @pytest.fixture |
| 91 | + def sample_list() -> List[int]: |
| 92 | + return [5, 10, 15] |
| 93 | +
|
| 94 | +
|
| 95 | + def test_sample_list(sample_list: List[int]) -> None: |
| 96 | + assert sum(sample_list) == 30 |
| 97 | +In this example, `List[int]` ensures that the list contains only integers, allowing functions like sum() to operate. |
| 98 | + |
| 99 | + |
| 100 | +.. code-block:: python |
| 101 | + from typing import Dict |
| 102 | + import pytest |
| 103 | +
|
| 104 | +
|
| 105 | + # Fixture returning a dictionary |
| 106 | + @pytest.fixture |
| 107 | + def sample_dict() -> Dict[str, int]: |
| 108 | + return {"a": 50, "b": 100} |
| 109 | +
|
| 110 | +
|
| 111 | + def test_sample_dict(sample_dict: Dict[str, int]) -> None: |
| 112 | + assert sample_dict["a"] == 50 |
| 113 | +In this example, `Dict[str, int]` ensures that each key is a string and each value is an integer, ensuring clarity and consistency when accessing dictionary elements by key. |
| 114 | + |
| 115 | + |
| 116 | +4. Typing Parameterized Tests |
| 117 | +---------- |
| 118 | +`@pytest.mark.parametrize` allows developer to run the test multiple times with different sets of arguments. |
| 119 | +Adding types helps to maintain consistency of values, especially for complex inputs. |
| 120 | + |
| 121 | +For example, you are testing if adding 1 to `input_value` results in `expected_output` for each set of arguments. |
| 122 | + |
| 123 | +.. code-block:: python |
| 124 | + import pytest |
| 125 | +
|
| 126 | +
|
| 127 | + @pytest.mark.parametrize("input_value, expected_output", [(1, 2), (5, 6), (100, 101)]) |
| 128 | + def test_increment(input_value: int, expected_output: int) -> None: |
| 129 | + assert input_value + 1 == expected_output |
| 130 | +
|
| 131 | +In this example: |
| 132 | +You are expecting the type of both `input_value` and `expected_output` are integers. |
| 133 | + |
| 134 | + |
| 135 | +Conclusion |
| 136 | +---------- |
| 137 | +Using typing in pytest helps improve readability of the tests and fixture returns, and prevent errors. |
0 commit comments