Как Pytest собирает тесты по модулям и классам
Что проверяют
Знаете ли вы механику сбора, а не только соглашение «называй файл test_». Интервьюера интересует, почему тест иногда молча не находится и как управлять сбором. Следом часто спрашивают про conftest.py и про то, что происходит с кодом на уровне модуля.
Как отвечать
Сбор начинается с путей из командной строки или из testpaths в конфиге, а если их нет, с текущего каталога. Pytest строит дерево узлов: сессия, каталоги и пакеты, модули, классы, функции. Правила задаются в pytest.ini, pyproject.toml (секция [tool.pytest.ini_options]), tox.ini или setup.cfg:
- каталоги: обходятся рекурсивно, кроме попавших под
norecursedirs(по умолчанию скрытые,build,dist,venv,node_modulesи ещё несколько); - файлы:
python_files, по умолчаниюtest_*.pyи*_test.py. Файл импортируется, и весь код верхнего уровня в нём исполняется; - классы:
python_classes, по умолчанию имя начинается сTest, и у класса не должно быть__init__. На каждый тестовый метод создаётся новый экземпляр. Наследникиunittest.TestCaseсобираются всегда, независимо от имени; - функции и методы:
python_functions, по умолчанию префиксtest.
У каждого теста есть идентификатор вида tests/test_api.py::TestUser::test_create, по нему запускают один тест. Параметризация через @pytest.mark.parametrize разворачивается ещё на этапе сбора в отдельные элементы с суффиксом в квадратных скобках. Посмотреть, что собралось, можно через pytest --collect-only -q, отфильтровать через -k и -m, а порядок и состав поправить хуком pytest_collection_modifyitems в conftest.py.
Где спотыкаются
Добавляют тестовому классу __init__ и не понимают, куда пропали тесты. Pytest выдаёт PytestCollectionWarning и класс не собирает.
Кладут одноимённые test_utils.py в разные каталоги без __init__.py. В режиме импорта по умолчанию (prepend) это даёт ошибку конфликта имён модулей; помогает __init__.py или --import-mode=importlib.
Держат на уровне модуля подключение к базе или запрос в сеть. Этот код выполнится при сборке, даже если через -k вы запускаете совсем другой тест. Такое уносят в фикстуры.