Можно ли как-то отлаживать с помощью отладчика python при использовании py.test?

Я использую py.test для модульного тестирования моей программы на Python. Я хочу отладить свой тестовый код с помощью отладчика Python обычным способом (под словом я имею в виду pdb.set_trace() в коде), но я не могу заставить его работать.

Помещение pdb.set_trace() в код не работает (вызывает IOError: чтение из stdin, пока вывод получен). Я также попытался запустить py.test с опцией --pdb, но, похоже, это не сработало, если я хочу изучить, что происходит до моего утверждения. Он прерывается, когда утверждение не выполняется, и переход от этой строки означает завершение программы.

Кто-нибудь знает способ получить отладку, или отладка и py.test просто не должны быть вместе?

7 ответов

Это очень просто: положить assert 0 где вы хотите начать отладку в своем коде и запустить свои тесты с:

py.test --pdb 

сделанный:)

Кроме того, если вы используете Pytest-2.0.1 или выше, также есть pytest.set_trace() помощник, который вы можете поместить в любом месте вашего тестового кода. Here are the docs. It will take care to internally disable capturing before sending you to the pdb debugger command-line.

Я обнаружил, что могу запустить py.test с отключенным захватом, а затем использовать pdb.set_trace() как обычно.

> py.test --capture=no
============================= test session starts ==============================
platform linux2 -- Python 2.5.2 -- pytest-1.3.3
test path 1: project/lib/test/test_facet.py

project/lib/test/test_facet.py ...> /home/jaraco/projects/project/lib/functions.py(158)do_something()
-> code_about_to_run('')
(Pdb)

Самый простой способ - использовать механизм py.test для создания точки останова.

http://pytest.org/latest/usage.html

import pytest
def test_function():
    ...
    pytest.set_trace()    # invoke PDB debugger and tracing

Или если вы хотите pytestОтладчик как однострочник, поменяй import pdb; pdb.set_trace() в import pytest; pytest.set_trace()

Подобно ответу Питера Лайона, но с точным кодом, который вам нужен для pytest, вы можете добавить следующее в нижнюю часть своего модуля pytest (my_test_module.py):

if __name__ == "__main__":
    pytest.main(["my_test_module.py", "-s"])

Затем вы можете вызвать отладчик из командной строки:

pdb3 my_test_module.py

Бум. Вы находитесь в отладчике и можете вводить команды отладчика. Этот метод оставляет ваш тестовый код незагроможденным вызовами set_trace() и будет работать внутри pytest "нормально".

Я не знаком с py.test, поставил для unittest, вы делаете следующее. Может быть, py.test похож:

В вашем тестовом модуле (mytestmodule.py):

if __name__ == "__main__":
    unittest.main(module="mytestmodule")

Затем запустите тест с

python -m pdb mytestmodule.py

Вы получите интерактивную оболочку pdb.

Глядя на документы, похоже, что py.test имеет --pdb опция командной строки:

http://codespeak.net/py/dist/test/features.html

Просто используйте: pytest --trace test_your_test.py. Это вызовет отладчик Python в начале теста.

Добавление и удаление точек останова без редактирования исходных файлов

Хотя вы можете добавить точки останова, добавив breakpoint() или же set_trace() операторов в ваш код, у этого подхода есть две проблемы:

  • Во-первых, после того, как вы начали запускать свой код, удалить точку останова невозможно. Я часто обнаруживаю, что как только я запускаю свой код и достигаю начальной точки останова, я хочу разместить еще одну и удалить начальную точку останова. После breakpoint()бросает меня в отладчик, я могу добавить дополнительные точки останова, но не могу удалить начальную. Хотя это можно несколько смягчить, поставив начальное breakpointвыше, если у вас есть параметризованные тесты, то даже это ограничено. Я могу повторять cont очень часто.
  • Во-вторых, это требует изменения исходного кода. Вам нужно не забыть удалить все breakpoint()перед тем, как передать какой-либо код в систему управления версиями, вы должны удалить их перед переключением ветвей и т. д. Иногда я обнаруживаю, что хочу использовать отладчик для сравнения тестовых прогонов между двумя ветвями, и необходимость редактировать исходный код, чтобы каждый раз добавлять точку останова делает это упражнение значительно более медленным и более подверженным ошибкам. Возможно, я даже захочу добавить точку останова в вызываемой мной библиотеке, и в этом случае файл, который я редактирую, может находиться даже не в моем репозитории git, а где-то глубоко в моей среде conda, что увеличивает риск того, что я забуду его удалить. По моему скромному мнению, редактировать файлы для добавления точек останова некрасиво.

Чтобы добавлять и удалять точки останова в интерактивном режиме без редактирования исходных файлов, вы можете вызвать pytest следующим образом (в оболочке bash):

python -mipdb $(type -p pytest) -s test_fileset.py

В -sflag здесь имеет решающее значение, потому что он не позволяет pytest связываться со стандартным вводом и выводом, а при запуске внутри отладчика pytest не сможет взаимодействовать со стандартным вводом и выводом, и все пойдет не так. Точный синтаксис вызова будет отличаться для разных оболочек.

Другие вопросы по тегам