Ответ
В Pytest декораторы — это ключевой механизм для настройки и управления поведением тестовых функций, классов и фикстур. Они позволяют добавлять метаданные и логику, не загрязняя сам тестовый код.
Основные встроенные декораторы и их назначение:
-
@pytest.mark— для маркировки тестов:@pytest.mark.skip— пропустить тест.@pytest.mark.skipif— пропустить при выполнении условия.@pytest.mark.parametrize— запустить тест с разными наборами данных.@pytest.mark.xfail— отметить, что тест ожидаемо падает.- Пользовательские маркеры (например,
@pytest.mark.slow,@pytest.mark.api) для группировки и выборочного запуска.
-
@pytest.fixture— для создания фикстур:- Фикстуры предоставляют данные, состояние или ресурсы для тестов (например, подключение к БД, тестовый клиент API).
-
@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 — это вообще отдельная песня, ебать мои старые костыли. По сути, это такие волшебные палочки, которыми ты размахиваешь над своей функцией, и она сразу начинает вести себя не как все. Не надо городить овердохуища кода внутри, просто накинул сверху штуку — и всё, магия готова.
Основные приколюхи, которые всегда под рукой:
-
@pytest.mark— это как бирка на ухе. Вешаешь — и всё, тест помечен.@pytest.mark.skip— просто послать тест на хуй, не запуская. Устарел, не работает, пофиг.@pytest.mark.skipif— умный пропуск. «Если у нас версия Python старше, чем мои тапки, то даже не пытайся».@pytest.mark.parametrize— вот это сила, ёпта! Одна функция, а гоняешь её с кучей разных данных. Красота.@pytest.mark.xfail— хитрая жопа. Тест должен упасть, и если он падает — всё ок, молодец. Если вдруг проходит — вот тут подозрение ебать чувствую, что-то не так.- Свои маркеры (
@pytest.mark.slow) — чтобы потом запускать только быстрые тесты, а медленные, которые жрут время, отложить на потом.
-
@pytest.fixture— царь и бог. Это подготовка всего, что нужно тесту: база данных, клиент, тестовые файлы. Создал один раз — используй где угодно. Главное, не забудьyield, чтобы потом почистить за собой, а то ресурсы повиснут. -
@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
Короче, вся фишка в том, что декораторы делают твой тестовый код чистым и понятным. Всё, что касается настройки, условий, данных — висит сверху, как инструкция. А сам тест — это просто голая логика проверки. Удобно, ёклмн.