Для чего нужен декоратор в Pytest?

Ответ

В Pytest декораторы — это ключевой механизм для настройки и управления поведением тестовых функций, классов и фикстур. Они позволяют добавлять метаданные и логику, не загрязняя сам тестовый код.

Основные встроенные декораторы и их назначение:

  1. @pytest.mark — для маркировки тестов:

    • @pytest.mark.skip — пропустить тест.
    • @pytest.mark.skipif — пропустить при выполнении условия.
    • @pytest.mark.parametrize — запустить тест с разными наборами данных.
    • @pytest.mark.xfail — отметить, что тест ожидаемо падает.
    • Пользовательские маркеры (например, @pytest.mark.slow, @pytest.mark.api) для группировки и выборочного запуска.
  2. @pytest.fixture — для создания фикстур:

    • Фикстуры предоставляют данные, состояние или ресурсы для тестов (например, подключение к БД, тестовый клиент API).
  3. @pytest.hookimpl — для написания плагинов:

    • Позволяет перехватывать и модифицировать внутренние события Pytest (например, логирование, обработка результатов).

Практический пример с параметризацией и фикстурой:

import pytest

@pytest.fixture
def database_connection():
    # Имитация установки соединения с БД
    conn = {"status": "connected"}
    yield conn  # Возвращаем ресурс тесту
    # Закрытие соединения после теста (код после yield)
    conn["status"] = "closed"
    print("Соединение закрыто")

@pytest.mark.parametrize("user_id, user_name", [
    (1, "Alice"),
    (2, "Bob"),
])
def test_user_exists(database_connection, user_id, user_name):
    # Тест использует и фикстуру, и параметризацию
    assert database_connection["status"] == "connected"
    # Имитация запроса к БД
    mock_db = {1: "Alice", 2: "Bob"}
    assert mock_db[user_id] == user_name

Декораторы в Pytest делают тесты более декларативными, удобочитаемыми и легко поддерживаемыми.

Ответ 18+ 🔞

Слушай, ну декораторы в Pytest — это вообще отдельная песня, ебать мои старые костыли. По сути, это такие волшебные палочки, которыми ты размахиваешь над своей функцией, и она сразу начинает вести себя не как все. Не надо городить овердохуища кода внутри, просто накинул сверху штуку — и всё, магия готова.

Основные приколюхи, которые всегда под рукой:

  1. @pytest.mark — это как бирка на ухе. Вешаешь — и всё, тест помечен.

    • @pytest.mark.skip — просто послать тест на хуй, не запуская. Устарел, не работает, пофиг.
    • @pytest.mark.skipif — умный пропуск. «Если у нас версия Python старше, чем мои тапки, то даже не пытайся».
    • @pytest.mark.parametrize — вот это сила, ёпта! Одна функция, а гоняешь её с кучей разных данных. Красота.
    • @pytest.mark.xfail — хитрая жопа. Тест должен упасть, и если он падает — всё ок, молодец. Если вдруг проходит — вот тут подозрение ебать чувствую, что-то не так.
    • Свои маркеры (@pytest.mark.slow) — чтобы потом запускать только быстрые тесты, а медленные, которые жрут время, отложить на потом.
  2. @pytest.fixture — царь и бог. Это подготовка всего, что нужно тесту: база данных, клиент, тестовые файлы. Создал один раз — используй где угодно. Главное, не забудь yield, чтобы потом почистить за собой, а то ресурсы повиснут.

  3. @pytest.hookimpl — для самых ебанутых. Когда тебе мало встроенных возможностей и хочется ковыряться в кишках самого Pytest, чтобы подстроить его под себя. Это уже уровень «я сам от себя охуел».

Смотри, как это в жизни выглядит, на простом примере:

import pytest

@pytest.fixture
def database_connection():
    # Притворяемся, что подключились к базе
    conn = {"status": "connected"}
    yield conn  # Вот тут отдаём соединение тесту
    # А это выполнится ПОСЛЕ теста, чтобы прибраться
    conn["status"] = "closed"
    print("Соединение закрыто, не паникуй")

@pytest.mark.parametrize("user_id, user_name", [
    (1, "Alice"),
    (2, "Bob"),
])
def test_user_exists(database_connection, user_id, user_name):
    # Тест получает и фикстуру (базу), и параметры (айдишники)
    assert database_connection["status"] == "connected"
    # Ну допустим, у нас такая вот кривая тестовая база
    mock_db = {1: "Alice", 2: "Bob"}
    # Проверяем, что для переданного ID имя совпадает
    assert mock_db[user_id] == user_name

Короче, вся фишка в том, что декораторы делают твой тестовый код чистым и понятным. Всё, что касается настройки, условий, данных — висит сверху, как инструкция. А сам тест — это просто голая логика проверки. Удобно, ёклмн.