Ответ
Pytest ищет фикстуры, начиная с самого близкого к тесту контекста, двигаясь вверх по иерархии. Порядок приоритета следующий:
- Тестовый модуль (файл
.py): Фикстуры, объявленные в самом файле с тестом. - Файл
conftest.pyв текущей директории. - Файлы
conftest.pyв родительских директориях (по цепочке вверх до корня проекта). - Встроенные фикстуры pytest (например,
tmpdir,monkeypatch).
Пример структуры проекта:
project/
├── conftest.py # (3) Фикстуры для всего проекта (напр., драйвер)
├── tests/
│ ├── conftest.py # (2) Фикстуры для всех UI-тестов (напр., логин)
│ ├── ui/
│ │ ├── conftest.py # (2) Фикстуры для конкретной страницы
│ │ └── test_login.py # (1) Локальная фикстура `test_user_data`
│ └── api/
│ └── test_users.py # Использует фикстуры из tests/conftest.py и project/conftest.py
Практическое правило: Если фикстура с одинаковым именем существует в нескольких местах, будет использована наиболее локальная (с наивысшим приоритетом). Это позволяет переопределять общие фикстуры для конкретных подкаталогов.
Пример переопределения:
В project/conftest.py может быть общая фикстура driver(), а в tests/ui/conftest.py я могу переопределить её, чтобы добавить настройки именно для UI-тестов, например, максимализировать окно:
# project/conftest.py
import pytest
from selenium import webdriver
@pytest.fixture(scope="session")
def driver():
driver = webdriver.Chrome()
yield driver
driver.quit()
# tests/ui/conftest.py
import pytest
@pytest.fixture(scope="session")
def driver(driver): # Принимаем фикстуру из родительского conftest
driver.maximize_window()
yield driver
# Закрытие выполнится в родительской фикстуре
Понимание этого порядка критично для организации фикстур и избежания конфликтов в больших тестовых наборах.