Писал ли кастомные декораторы в Pytest?

«Писал ли кастомные декораторы в Pytest?» — вопрос из категории Фреймворки тестирования, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, писал. Стандартных декораторов Pytest часто недостаточно для сложной логики управления тестами. Я создавал собственные декораторы для решения специфичных задач проекта.

Пример 1: Декоратор для повторного запуска упавших тестов только в определенном окружении.

import pytest
import os

def retry_on_staging(f):
    """Декоратор, который повторяет падающий тест 2 раза, но только если переменная окружения ENV=staging."""
    def wrapper(*args, **kwargs):
        max_retries = 2 if os.getenv('ENV') == 'staging' else 0
        for attempt in range(max_retries + 1):
            try:
                return f(*args, **kwargs)
            except AssertionError as e:
                if attempt == max_retries:
                    raise e
                print(f"Retry {attempt + 1} for {f.__name__} due to {e}")
    return wrapper

@retry_on_staging
def test_flaky_api_integration():
    response = make_api_call()
    assert response.status_code == 200

Пример 2: Декоратор для логирования времени выполнения теста.

import time
import functools

def log_execution_time(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        print(f"{func.__name__} executed in {end_time - start_time:.4f} seconds")
        return result
    return wrapper

@pytest.mark.smoke
@log_execution_time
def test_heavy_report_generation():
    # ... логика теста
    assert report.is_valid()

Зачем это нужно:

  • Кастомизация логики: Добавление специфичных пред- или постусловий для группы тестов.
  • Улучшение отчетности: Сбор дополнительных метрик (время, использование памяти).
  • Управление flaky-тестами: Логика повторных запусков, более гибкая, чем @pytest.mark.flaky.
  • Интеграция: Связка тестов с внешними системами (например, простановка тегов в TestRail).