Как в pytest автоматически выполнять код до и после каждого теста

Ответ

Для автоматического выполнения кода до и после каждого теста в pytest используется фикстура с параметром autouse=True. Это позволяет инкапсулировать логику подготовки (setup) и очистки (teardown) без явного указания фикстуры в аргументах теста.

Код до инструкции yield выполняется перед тестом (setup), а код после yield — после его завершения (teardown).

Пример: Очистка тестовой таблицы в базе данных перед каждым тестом.

import pytest

# Условный объект для работы с БД
class Database:
    def clear_users_table(self):
        print("n[SETUP] Clearing users table...")

    def close_connection(self):
        print("[TEARDOWN] Closing connection...")

db = Database()

@pytest.fixture(scope="function", autouse=True)
def db_cleanup():
    # Код до yield - подготовка
    db.clear_users_table()
    yield
    # Код после yield - очистка
    db.close_connection()

def test_user_creation():
    print("Running test_user_creation...")
    assert True

def test_user_deletion():
    print("Running test_user_deletion...")
    assert True

Когда это полезно:

  • Управление ресурсами: Подключение и отключение от баз данных, запуск/остановка Docker-контейнеров.
  • Очистка состояния: Удаление временных файлов, сброс таблиц в БД, очистка mock-объектов.
  • Конфигурация окружения: Установка переменных окружения или глобальных настроек для тестов.

Ответ 18+ 🔞

Ах ты ж, ёпта, смотри-ка на какую тему налетел! Автоматическое выполнение кода до и после тестов в pytest. Ну это ж, блядь, святое дело — чтобы не писать одно и то же в каждом тесте, как последнему распиздую.

Так вот, слушай сюда, есть такая штука — фикстура. Берёшь её, настраиваешь параметр autouse=True, и она, сука, начинает работать сама, как проклятая. Ничего ей в аргументы теста пихать не надо, она сама всё сделает. Красота же, а?

Вся магия в yield. Всё, что до него — это подготовка, типа «setup». Всё, что после — это уборка за собой, «teardown». Как будто пришёл, насрал в унитаз, а потом спустил воду. Порядок, блядь.

Вот тебе живой пример: Допустим, у тесть база данных, и перед каждым тестом надо таблицу users зачистить, чтобы предыдущие тесты не нагадили.

import pytest

# Условный объект для работы с БД
class Database:
    def clear_users_table(self):
        print("n[SETUP] Clearing users table...")

    def close_connection(self):
        print("[TEARDOWN] Closing connection...")

db = Database()

@pytest.fixture(scope="function", autouse=True)
def db_cleanup():
    # Код до yield - подготовка
    db.clear_users_table()
    yield
    # Код после yield - очистка
    db.close_connection()

def test_user_creation():
    print("Running test_user_creation...")
    assert True

def test_user_deletion():
    print("Running test_user_deletion...")
    assert True

Запустишь это — и увидишь, как перед каждым тестом таблица чистится, а после — соединение закрывается. Автоматом, блядь! В рот меня чих-пых, удобно же.

А когда эта хрень особенно полезна?

  • Ресурсы всякие: Чтобы не забыть подключиться к базе или контейнер Docker запустить, а потом нахуй закрыть.
  • Уборка бардака: Удалить временные файлы, которые нагенерировались, или моков почистить. Чтобы не было, как в коммуналке — все друг другу мешают.
  • Окружение настроить: Выставить переменные или флаги, которые нужны всем тестам в этом модуле.

Вот и вся философия. Не усложняй, блядь. Сделал фикстуру с autouse — и живи спокойно, пока тесты бегают. Главное, чтобы логика внутри не была, как у мартышлюшки, а то всё поломаешь.