Изменение стандартного (Python) обнаружения тестов¶
Игнорирование путей во время сбора тестов¶
Вы можете легко игнорировать определенные тестовые каталоги и модули во время сбора, передавая опцию --ignore=path
на cli. pytest
позволяет использовать несколько опций --ignore
. Пример:
tests/
|-- example
| |-- test_example_01.py
| |-- test_example_02.py
| '-- test_example_03.py
|-- foobar
| |-- test_foobar_01.py
| |-- test_foobar_02.py
| '-- test_foobar_03.py
'-- hello
'-- world
|-- test_world_01.py
|-- test_world_02.py
'-- test_world_03.py
Теперь, если вы вызовете pytest
с --ignore=tests/foobar/test_foobar_03.py --ignore=tests/hello/
, вы увидите, что pytest
собирает только те тест-модули, которые не соответствуют заданным шаблонам:
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-5.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR, inifile:
collected 5 items
tests/example/test_example_01.py . [ 20%]
tests/example/test_example_02.py . [ 40%]
tests/example/test_example_03.py . [ 60%]
tests/foobar/test_foobar_01.py . [ 80%]
tests/foobar/test_foobar_02.py . [100%]
========================= 5 passed in 0.02 seconds =========================
Опция --ignore-glob
позволяет игнорировать пути к тестовым файлам, основанные на подстановочных знаках в стиле Unix shell. Если вы хотите исключить тестовые модули, которые заканчиваются на _01.py
, выполните pytest
с --ignore-glob='*_01.py'
.
Отмена выбора тестов во время сбора тестов¶
Тесты можно по отдельности отменить выборку во время сбора, передав параметр --deselect=item
. Например, допустим, tests/foobar/test_foobar_01.py
содержит test_a
и test_b
. Вы можете запустить все тесты внутри tests/
за исключением tests/foobar/test_foobar_01.py::test_a
, вызвав pytest
с помощью --deselect tests/foobar/test_foobar_01.py::test_a
. pytest
допускает несколько вариантов --deselect
.
Сохранение дубликатов путей, заданных из командной строки¶
По умолчанию pytest
игнорирует дубликаты путей, заданных из командной строки. Пример:
pytest path_a path_a
...
collected 1 item
...
Достаточно собрать тесты один раз.
Чтобы собрать дубликаты тестов, используйте опцию --keep-duplicates
в cli. Пример:
pytest --keep-duplicates path_a path_a
...
collected 2 items
...
Поскольку коллектор работает только с каталогами, если вы дважды укажете один тестовый файл, pytest
все равно соберет его дважды, независимо от того, не указан ли --keep-duplicates
. Пример:
pytest test_a.py test_a.py
...
collected 2 items
...
Изменение рекурсии каталогов¶
Вы можете установить опцию norecursedirs
в ini-файле, например, в вашем pytest.ini
в корневом каталоге проекта:
# content of pytest.ini
[pytest]
norecursedirs = .svn _build tmp*
Это указывает pytest
не выполнять поиск в обычных каталогах subversion или sphinx-build или в любом каталоге с префиксом tmp
.
Изменение соглашений об именовании¶
Вы можете настроить различные соглашения об именовании, установив python_files
, python_classes
и python_functions
в вашем configuration file. Вот пример:
# content of pytest.ini
# Example 1: have pytest look for "check" instead of "test"
[pytest]
python_files = check_*.py
python_classes = Check
python_functions = *_check
Это заставит pytest
искать тесты в файлах, соответствующих шаблону check_* .py
, префиксы Check
в классах, а также функции и методы, соответствующие шаблону *_check
. Например, если у нас есть:
# content of check_myapp.py
class CheckMyApp:
def simple_check(self):
pass
def complex_check(self):
pass
Коллекция тестов будет выглядеть следующим образом:
$ pytest --collect-only
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project, configfile: pytest.ini
collected 2 items
<Module check_myapp.py>
<Class CheckMyApp>
<Function simple_check>
<Function complex_check>
======================== 2 tests collected in 0.12s ========================
Вы можете проверить наличие нескольких шаблонов glob, добавив пробел между шаблонами:
# Example 2: have pytest look for files with "test" and "example"
# content of pytest.ini
[pytest]
python_files = test_*.py example_*.py
Примечание
опции python_functions
и python_classes
не имеют эффекта для обнаружения тестов unittest.TestCase
, поскольку pytest делегирует обнаружение методов тестового случая коду unittest.
Интерпретация аргументов cmdline как пакетов Python¶
Вы можете использовать опцию --pyargs
, чтобы заставить pytest
попробовать интерпретировать аргументы как имена пакетов python, вывести их путь к файловой системе и затем запустить тест. Например, если у вас установлен unittest2, вы можете набрать:
pytest --pyargs unittest2.test.test_skipping -q
что приведет к запуску соответствующего тестового модуля. Как и в случае с другими опциями, с помощью ini-файла и опции addopts
вы можете сделать это изменение более постоянным:
# content of pytest.ini
[pytest]
addopts = --pyargs
Теперь простой вызов pytest NAME
будет проверять, существует ли NAME как импортируемый пакет/модуль, и в противном случае рассматривать его как путь к файловой системе.
Выяснение того, что собрано¶
Вы всегда можете заглянуть в дерево коллекций без выполнения подобных тестов:
. $ pytest --collect-only pythoncollection.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project, configfile: pytest.ini
collected 3 items
<Module CWD/pythoncollection.py>
<Function test_function>
<Class TestClass>
<Function test_method>
<Function test_anothermethod>
======================== 3 tests collected in 0.12s ========================
Настройка сбора тестов¶
Вы можете легко поручить pytest
обнаружить тесты из каждого файла Python:
# content of pytest.ini
[pytest]
python_files = *.py
Однако во многих проектах есть setup.py
, которые они не хотят импортировать. Более того, могут существовать файлы, импортируемые только определенной версией python. Для таких случаев вы можете динамически определить файлы, которые будут игнорироваться, перечислив их в файле conftest.py
:
# content of conftest.py
import sys
collect_ignore = ["setup.py"]
if sys.version_info[0] > 2:
collect_ignore.append("pkg/module_py2.py")
и затем, если у вас есть файл модуля, например, такой:
# content of pkg/module_py2.py
def test_only_on_python2():
try:
assert 0
except Exception, e:
pass
и такой фиктивный файл setup.py
:
# content of setup.py
0 / 0 # will raise exception if imported
Если вы работаете с интерпретатором Python 2, то вы найдете один тест и оставите файл setup.py
:
#$ pytest --collect-only
====== test session starts ======
platform linux2 -- Python 2.7.10, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
collected 1 items
<Module 'pkg/module_py2.py'>
<Function 'test_only_on_python2'>
====== 1 tests found in 0.04 seconds ======
Если вы запускаете с интерпретатором Python 3, то и один тест, и файл setup.py
будут пропущены:
$ pytest --collect-only
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project, configfile: pytest.ini
collected 0 items
======================= no tests collected in 0.12s ========================
Также можно игнорировать файлы на основе подстановочных знаков в стиле Unix shell, добавляя шаблоны к collect_ignore_glob
.
Следующий пример conftest.py
игнорирует файл setup.py
и, кроме того, все файлы, которые заканчиваются на *_py2.py
при выполнении интерпретатором Python 3:
# content of conftest.py
import sys
collect_ignore = ["setup.py"]
if sys.version_info[0] > 2:
collect_ignore_glob = ["*_py2.py"]
Начиная с Pytest 2.6, пользователи могут запретить pytest обнаруживать классы, начинающиеся с Test
, установив булев атрибут __test__
в значение False
.
# Will not be discovered as a test
class TestClass:
__test__ = False