Spec-Zone.ru › pytest

Типизация в pytest

Примечание

Предполагается, что читатель знаком с системой типизации Python и её преимуществами.

Дополнительную информацию см. в документации по типизации Python.

Зачем нужны тесты с типизацией?

Типизация тестов даёт значительные преимущества:

  • Читаемость: чётко определяет ожидаемые входные и выходные данные, повышая читаемость, особенно в сложных тестах и тестах с параметризацией.
  • Рефакторинг: это главное преимущество типизации тестов: она значительно упрощает рефакторинг, позволяя средству проверки типов указать на необходимые изменения как в рабочем коде, так и в тестах, без необходимости запускать весь набор тестов.

Типизация рабочего кода также помогает обнаруживать некоторые ошибки, которые могут быть не выявлены тестами вовсе (независимо от покрытия), например:

def get_caption(target: int, items: list[tuple[int, str]]) -> str:
    for value, caption in items:
        if value == target:
            return caption

Средство проверки типов правильно сообщит об ошибке, что функция может вернуть None, однако даже набор тестов с полным покрытием может не выявить этот случай:

def test_get_caption() -> None:
    assert get_caption(10, [(1, "foo"), (10, "bar")]) == "bar"

Обратите внимание: приведённый выше код имеет покрытие 100%, но ошибка не обнаруживается (конечно, пример «очевидный», но он помогает проиллюстрировать мысль).

Использование типизации в наборах тестов

Чтобы указать типы фикстур в pytest, просто добавьте обычные аннотации типов к функциям фикстур — особых действий из-за декоратора fixture не требуется.

import pytest


@pytest.fixture
def sample_fixture() -> int:
    return 38

Аналогичным образом фикстуры, передаваемые тестовым функциям, должны быть аннотированы типом возвращаемого значения фикстуры:

def test_sample_fixture(sample_fixture: int) -> None:
    assert sample_fixture == 38

С точки зрения средства проверки типов не имеет значения, что sample_fixture на самом деле является фикстурой, управляемой pytest; важно лишь то, что sample_fixture — это параметр типа int.

Та же логика применима к @pytest.mark.parametrize:

@pytest.mark.parametrize("input_value, expected_output", [(1, 2), (5, 6), (10, 11)])
def test_increment(input_value: int, expected_output: int) -> None:
    assert input_value + 1 == expected_output

Та же логика применима при указании типов функций фикстур, принимающих другие фикстуры:

@pytest.fixture
def mock_env_user(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setenv("USER", "TestingUser")

Заключение

Добавление типизации в тесты pytest повышает ясность, упрощает отладку и сопровождение, а также обеспечивает безопасность типов. Эти практики позволяют создать надёжный, понятный и удобный в сопровождении набор тестов, который лучше подготовлен к будущим изменениям и сводит к минимуму риск ошибок.

© 2015–2026 Holger Krekel and pytest-dev team
Licensed under the MIT License.
https://docs.pytest.org/en/stable/explanation/types.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API