Сообщить об ошибке.

Использование PDB отладчика и faulthandler с pytest

Содержание:


Вызов отладчика PDB при тестировании.

C помощью опции командной строки фреймворк pytest позволяет перейти в приглашение PDB сразу же в начале каждого теста:

$ pytest --trace

Такой запуск тестов вызовет отладчик Python в начале каждого теста.

Переход к PDB-отладчику при сбоях тестов.

Python поставляется со встроенным отладчиком pdb. Фреймворк pytest позволяет перейти в приглашение pdb, используя опции командной строки: $ pytest --pdb. Данная команда будет вызывать отладчик Python при каждом сбое (или прерывании клавиатуры Ctrl+C). Чтобы понять определенную ситуацию сбоя, вызов отладчика Python необходимо только для первого неудачного теста:

# перейдите в PDB при первом сбое, затем завершите тестовый сеанс
pytest -x --pdb
# переход к PDB для первых трех сбоев
pytest --pdb --maxfail=3

Обратите внимание, что при любом сбое, информация об исключении сохраняется в sys.last_value, sys.last_type и sys.last_traceback. При интерактивном использовании это позволяет перейти к "посмертной" отладке с помощью любого инструмента. Можно также вручную получить доступ к информации об исключении, например:

>>> import sys
>>> sys.last_traceback.tb_lineno
# 42
>>> sys.last_value
# AssertionError('assert result == "ok"',)

Установка точек останова.

Чтобы установить точку останова в коде, необходимо использовать собственный вызов Python import pdb;pdb.set_trace(), и pytest автоматически отключит перехват вывода для этого теста:

  • Перехват вывода в других тестах не затрагивается.
  • Весь перехваченный ранее вывод будет обработан как есть;
  • Перехват вывода возобновляется при завершении сеанса отладчика (через команду continue).

Использование функции breakpoint().

Python 3.7 представляет встроенную функцию breakpoint(). Pytest поддерживает использование breakpoint() со следующим поведением:

  • Когда вызывается breakpoint() и для PYTHONBREAKPOINT установлено значение по умолчанию, то pytest будет использовать настраиваемый трассировщик PDB вместо системного по умолчанию.
  • Когда тесты будут завершены, система по умолчанию вернется к системному интерфейсу трассировки.
  • Когда pytest вызывается с опцией --pdb, то настраиваемый трассировщик PDB используется как с breakpoint(), так и с неудачными тестами/необработанными исключениями.
  • для указания пользовательского класса отладчика можно использовать опцию --pdbcls.

Использование модуля faulthandler.

Для сброса трассировок при ошибке или по истечении времени ожидания можно использовать стандартный модуль faulthandler.

При запуске pytest модуль faulthandler подключается автоматически, если только в командной строке не используется опция -p no:faulthandler. Кроме того, в случае, когда тест длится более X секунд, для сброса трассировок всех потоков можно использовать настройку faulthandler_timeout=X (недоступно в Windows).

# устанавливается в 
# файле pytest.ini
[pytest]
faulthandler_timeout=5
  • опция настройки faulthandler_timeout сбрасывает трассировку всех потоков, если выполнение теста занимает больше X секунд (включая установку и отключение фикстуры). Реализовано с помощью функции faulthandler.dump_traceback_later().

Примечание

Эта функциональность была интегрирована из внешнего плагина pytest-faulthandler с двумя небольшими изменениями:

  • чтобы ее отключить, используйте опцию CLI -p no:faulthandler вместо --no-faulthandler;
  • опция командной строки --faulthandler-timeout превратилась в опцию настройки faulthandler_timeout. Ее по-прежнему можно настроить из команндной строки, используя -o faulthandler_timeout=X.

Недопустимые исключения и необработанные исключения потоков.

Эти функции работают только на Python >= 3.8.

Необработанные исключения - это исключения, возникающие в ситуации, когда они не могут быть переданы вызывающему объекту. Наиболее распространенным случаем является исключение, возникающее в реализации __del__.

Необработанные исключения потока - это исключения, вызванные в потоке, но не обработанные, что приводит к нечистому завершению потока.

Оба типа исключений обычно считаются ошибками, но могут остаться незамеченными, так как не приводят к сбою самой программы. Фреймворк pytest обнаруживает эти условия и выдает предупреждение, которое отображается в сводке выполнения теста.

При запуске pytest автоматически включаются необходимые инструменты, если только в командной строке не задана опция CLI -p no:unraisableexception (для необрабатываемых исключений) и -p no:threadexception (для исключений потоков).

Предупреждения могут быть отключены выборочно с помощью метки/декоратора @pytest.mark.filterwarning().

Категории предупреждений:

  • pytest.PytestUnraisableExceptionWarning;
  • pytest.PytestUnhandledThreadExceptionWarning.