Полное руководство по областям действия фикстур и параметризации в Pytest
Scopes определяют, как часто фикстура запускается. Это ключевой механизм управления жизненным циклом тестовых данных.
| Scope | Описание | Когда запускается |
|---|---|---|
function | По умолчанию | Для каждой тестовой функции |
class | На уровне класса | Один раз на класс, независимо от количества методов |
module | На уровне модуля | Один раз на файл .py |
session | На уровне сессии | Один раз на всю сессию pytest |
@pytest.fixture def database_connection(): print("\n[SETUP] Создание подключения к БД") conn = "DB Connection Object" yield conn print("\n[TEARDOWN] Закрытие подключения к БД") def test_user_login(database_connection): print(f"\n[Test] Используем: {database_connection}") assert True
Важно: Фикстура запускается 2 раза — по одному для каждой тестовой функции. Это может быть проблемой, если создание соединения дорогостоящая операция.
@pytest.fixture(scope="class") def api_client(): print("\n[SETUP] Создание API клиента") client = "API Client" yield client print("\n[TEARDOWN] Закрытие API клиента") class TestUserAPI: def test_login(self, api_client): assert True def test_get_profile(self, api_client): assert True
Важно: Фикстура запускается 1 раз на весь класс. Все три теста используют один и тот же объект api_client.
@pytest.fixture(scope="module") def test_database(): print("\n[SETUP MODULE] Инициализация тестовой БД") db = "Test Database" yield db print("\n[TEARDOWN MODULE] Удаление тестовой БД")
Важно: Все тесты в модуле (включая класс) используют один и тот же test_database.
# conftest.py или любой модуль @pytest.fixture(scope="session") def browser_driver(): print("\n[SETUP SESSION] Запуск Browser Driver") driver = "Chrome Driver" yield driver print("\n[TEARDOWN SESSION] Закрытие Browser Driver")
Важно: browser_driver создается один раз и используется во всех тестовых файлах сессии.
@pytest.fixture(scope="class", autouse=True) def setup_database(): print("\n[SETUP] Подключение к БД") db = "Database Connection" yield db print("\n[TEARDOWN] Отключение от БД") class TestDatabaseOperations: def test_insert(self): assert True
Примечание: autouse=True автоматически применяет фикстуру ко всем тестам без явного указания в параметрах.
Параметризация позволяет запускать один тест с разными наборами данных.
@pytest.mark.parametrize("input,expected", [ (1, 2), (3, 6), (5, 10) ]) def test_double(input, expected): assert input * 2 == expected
Важно: Тест запустится 3 раза с разными параметрами.
@pytest.fixture(params=["Chrome", "Firefox", "Safari"]) def browser(request): print(f"\n[SETUP] Запуск {request.param}") yield f"{request.param} Driver" print(f"\n[TEARDOWN] Закрытие {request.param}")
@pytest.fixture(scope="module", params=["PostgreSQL", "MySQL", "SQLite"]) def database(request): yield f"{request.param} Connection" @pytest.mark.parametrize("user_count", [1, 10, 100]) def test_insert_users(database, user_count): assert True
Важно: Фикстура database с scope="module" выполняется один раз для каждого уникального request.param. То есть: 3 базы × 3 количества = 9 тестов.
@pytest.fixture(scope="function") def api_token(): yield "ABC123" @pytest.mark.parametrize("endpoint", ["/users", "/orders", "/products"]) def test_api_endpoints(api_token, endpoint): assert True
3 теста × 2 вызова setup/teardown = 6 операций с токеном.
@pytest.fixture(scope="class") def shared_api_client(): print("\n[SETUP CLASS] Создание API клиента") yield "API Client Object" @pytest.mark.parametrize("endpoint", ["/users", "/orders"]) class TestAPIEndpoints: def test_get(self, shared_api_client, endpoint): assert True
Важно: API клиент создается один раз на класс, несмотря на 4 запуска тестов. Это оптимизация.
@pytest.fixture(scope="session") def config(): return {"base_url": "https://api.example.com", "timeout": 30} @pytest.fixture(scope="module") def api_client(config): return f"Client -> {config['base_url']}" @pytest.fixture(scope="function") def auth_token(api_client, config): return f"Token for {api_client}"
Порядок создания: config (session) → api_client (module) → auth_token (function)
@pytest.fixture(scope="function") def user_repository(db_connection): return f"UserRepository({db_connection})" @pytest.fixture(scope="function") def service(user_repository, order_repository): return f"Service({user_repository}, {order_repository})"
| Scope | 1 тест | 2 теста | 3 теста (1 класс) | 10 тестов (2 класса) |
|---|---|---|---|---|
function | 1 setup | 2 setups | 3 setups | 10 setups |
class | 1 setup | 1 setup | 1 setup | 2 setups |
module | 1 setup | 1 setup | 1 setup | 1 setup |
session | 1 setup | 1 setup | 1 setup | 1 setup |
Параметризация умножает количество запусков: если у вас 3 теста и 4 параметра — это 12 реальных запусков тестов.
Используйте по умолчанию, когда данные не должны шариться между тестами
Для тяжелых ресурсов, используемых несколькими тестами в одном классе (например, API клиент)
Для ресурсов, которые можно переиспользовать во всём модуле (БД, конфиг)
Для глобальных ресурсов (браузер, сессия авторизации)
Мощный инструмент, но помните: каждый уникальный набор параметров запускает фикстуру заново