Какие декораторы используются для тестирования в Python с помощью pytest

«Какие декораторы используются для тестирования в Python с помощью pytest» — вопрос из категории Тестирование, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Декораторы в pytest и других фреймворках позволяют декларативно управлять поведением тестов: параметризовать их, пропускать, помечать или подготавливать для них данные (фикстуры).

Ключевые декораторы:

  1. @pytest.fixture — определяет фикстуру, функцию для подготовки тестового окружения (например, соединение с БД, создание временных файлов) и его очистки после выполнения теста.

    import pytest
    
    @pytest.fixture(scope="module")
    def db_connection():
        # Код до yield выполняется перед тестами
        conn = create_connection()
        yield conn
        # Код после yield выполняется после тестов
        conn.close()
  2. @pytest.mark.parametrize — позволяет запустить один и тот же тест с разными наборами входных данных, что избавляет от дублирования кода.

    @pytest.mark.parametrize("test_input, expected", [
        (2, 4),
        (3, 9),
        (4, 16)
    ])
    def test_square(test_input, expected):
        assert test_input ** 2 == expected
  3. @pytest.mark.skip и @pytest.mark.skipif — используются для пропуска тестов. skip пропускает тест безусловно, а skipif — при выполнении определенного условия.

    import sys
    
    @pytest.mark.skip(reason="Тест еще не реализован")
    def test_new_feature():
        pass
    
    @pytest.mark.skipif(sys.version_info < (3, 10), reason="Требуется Python 3.10+")
    def test_feature_for_python310():
        pass
  4. @pytest.mark.xfail — помечает тест как "ожидаемо падающий". Тест будет запущен, но его падение не будет считаться ошибкой сборки. Это полезно для отслеживания известных багов.

    @pytest.mark.xfail(reason="Известный баг в API #123")
    def test_broken_api_call():
        assert call_api() is False
  5. @mock.patch (из unittest.mock) — широко используется вместе с pytest для мокирования (подмены) объектов, функций или классов во время теста, чтобы изолировать тестируемый код от внешних зависимостей.

    from unittest import mock
    
    @mock.patch("mymodule.external_service")
    def test_with_mock(mock_service):
        mock_service.get_data.return_value = {"status": "ok"}
        # ... вызов функции, использующей external_service