Приведи пример генератора в Pytest
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример генератора данных в Pytest
В Pytest под термином «генератор» часто подразумевают не классические генераторы Python (хотя их тоже можно использовать), а фикстуры (fixtures) с параметризацией, которые динамически генерируют данные для тестов. Это позволяет создавать гибкие и переиспользуемые источники тестовых данных.
Однако, если говорить о классических Python-генераторах (функциях с ключевым словом yield), то они также активно применяются в Pytest, особенно в составе фикстур. Рассмотрим оба подхода.
1. Генератор как фикстура с параметризацией (наиболее частая практика)
Вы можете создать фикстуру, которая возвращает функцию-генератор данных или использует yield для управления жизненным циклом. Но чаще под «генерацией» понимают динамическое создание параметров.
Пример: Фикстура, генерирующая тестовые данные
import pytest
import json
# Фикстура, которая "генерирует" разные конфигурации для теста
@pytest.fixture(params=[
{"user": "admin", "access": "full"},
{"user": "editor", "access": "partial"},
{"user": "viewer", "access": "readonly"}
])
def user_config(request):
"""Генератор конфигураций пользователей. Pytest вызовет тест для каждого param."""
config = request.param
config["active"] = True # Динамически добавляем поле
yield config # Используем yield как финализатор (опционально)
# Здесь можно, например, логировать завершение теста для этой конфигурации
print(f"Тест завершен для пользователя: {config['user']}")
def test_user_permissions(user_config):
"""Тест будет запущен 3 раза с разными user_config."""
assert "user" in user_config
assert user_config["active"] is True
# Проверяем логику в зависимости от сгенерированных данных
if user_config["user"] == "admin":
assert user_config["access"] == "full"
2. Фикстура как классический генератор Python (с yield)
Такие фикстуры часто используются для setup/teardown логики, но они также могут «генерировать» объекты по запросу.
import pytest
@pytest.fixture
def dynamic_data_generator():
"""Фикстура-генератор, которая отдает данные по одному, имитируя поток."""
data_points = [10, 20, 30, 40, 50]
def inner_generator():
for point in data_points:
yield point * 2 # Генерация модифицированных данных
# Возвращаем сам генератор, чтобы тест мог им управлять
return inner_generator()
def test_with_generator(dynamic_data_generator):
"""Тест, использующий переданный генератор напрямую."""
results = list(dynamic_data_generator)
assert results == [20, 40, 60, 80, 100]
# Или можно итерироваться по генератору в тесте
gen = dynamic_data_generator
first_value = next(gen)
assert first_value == 20
3. Параметризация тестов с помощью pytest.mark.parametrize и генераторов
Это самый мощный способ «генерации» данных. Вы можете использовать выражение-генератор (generator expression) прямо в декораторе.
import pytest
# Генерация пар вход-ожидание через генераторное выражение
def generate_test_cases():
"""Функция, возвращающая генератор кортежей (input, expected)."""
for i in range(5):
yield i, i * 2 # Классический генератор Python
# Преобразуем генератор в список для parametrize (требуется статический список)
test_data = list(generate_test_cases())
@pytest.mark.parametrize("input_value, expected", test_data)
def test_multiplication(input_value, expected):
"""Тест будет запущен 5 раз с данными из генератора."""
assert input_value * 2 == expected
4. Динамическая параметризация (pytest_generate_tests)
Для наиболее сложной динамической генерации параметров на этапе коллекции тестов используется хук pytest_generate_tests.
import pytest
def generate_dynamic_params():
"""Генерируем параметры на основе внешних условий, например, данных из файла."""
# Имитируем чтение из файла или БД
environments = ["dev", "stage", "prod"]
for env in environments:
yield env.upper(), env # Каждый yield — это один набор аргументов
def pytest_generate_tests(metafunc):
"""Хук Pytest для динамической параметризации."""
if "env_name" in metafunc.fixturenames and "env_code" in metafunc.fixturenames:
# Преобразуем генератор в список кортежей
params = list(generate_dynamic_params())
# Применяем параметризацию
metafunc.parametrize("env_name, env_code", params)
def test_environment_config(env_name, env_code):
"""Тест запустится 3 раза для DEV, STAGE, PROD."""
assert env_name == env_code.upper()
print(f"Запуск теста для окружения: {env_code}")
Ключевые выводы
- Основной механизм «генерации» в Pytest — это параметризация (
@pytest.mark.parametrizeилиparamsв фикстурах). - Классические генераторы Python (
yield) в Pytest чаще используются:
* В фикстурах для разделения кода setup и teardown.
* Для создания источников данных, которые можно превратить в список для параметризации.
- Для максимальной гибкости при динамическом создании данных используйте хук
pytest_generate_tests. - Все подходы направлены на одну цель: избежать дублирования кода и обеспечить полное покрытие различных входных данных и состояний системы.
Таким образом, «генератор в Pytest» — это, как правило, не один конкретный объект, а стратегия использования механизмов Pytest (фикстуры, параметризация) вместе с генераторами Python для эффективного создания разнообразных тестовых данных.