以某种方式使用py.test时,我可以使用python调试器进行调试吗?

时间:2010-04-20 21:28:15

标签: python unit-testing pdb

我正在使用py.test对我的python程序进行单元测试。我希望用python调试器以正常的方式调试我的测试代码(我的意思是代码中的pdb.set_trace())但是我无法使它工作。

将pdb.set_trace()放入代码中不起作用(引发IOError:在捕获输出时从stdin读取)。我也尝试使用选项--pdb运行py.test但是如果我想探索在断言之前发生的事情,那似乎并不起作用。它在断言失败时中断,从该行开始意味着终止程序。

有没有人知道调试的方法,或者调试和py.test只是不想在一起?

7 个答案:

答案 0 :(得分:82)

这很简单:将assert 0放在要在代码中开始调试的位置并运行测试:

py.test --pdb 

完成:)

或者,如果您使用的是pytest-2.0.1或更高版本,那么您还可以将pytest.set_trace()助手放在测试代码中的任何位置。这是docs。在将您发送到pdb调试器命令行之前,需要注意内部禁用捕获。

答案 1 :(得分:31)

我发现我可以在禁用捕获的情况下运行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)

答案 2 :(得分:17)

最简单的方法是使用py.test机制创建断点

http://pytest.org/latest/usage.html#setting-a-breakpoint-aka-set-trace

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

或者,如果您希望将pytest的调试程序作为一行,请将import pdb; pdb.set_trace()更改为import pytest; pytest.set_trace()

答案 3 :(得分:1)

我不熟悉py.test,为了进行单元测试,你会做以下事情。也许py.test类似:

在您的测试模块(mytestmodule.py)中:

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

然后用

运行测试
python -m pdb mytestmodule.py

您将获得一个交互式pdb shell。

查看文档,看起来py.test有一个--pdb命令行选项:

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

答案 4 :(得分:1)

与Peter Lyon的答案类似,但是有了pytest所需的确切代码,您可以将以下内容添加到pytest模块的底部(my_test_module.py):

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

然后您可以从命令行调用调试器:

pdb3 my_test_module.py

景气。您正在调试器中,并且能够输入调试器命令。这种方法不会让您的测试代码受到set_trace()调用的干扰,并且会在pytest中“正常”运行。

答案 5 :(得分:0)

添加并删除断点,而无需编辑源文件

尽管您可以通过在代码中添加breakpoint()set_trace()语句来添加断点,但是这种方法存在两个问题:

  • 首先,一旦开始运行代码,就无法删除断点。我经常发现,一旦我开始运行代码并到达初始断点,我想放置另一个代码并删除初始断点。在breakpoint()进入调试器后,我可以添加其他断点,但是不能删除初始断点。尽管可以通过将初始breakpoint放在较高的位置来缓解这种情况,但是,如果您有参数化测试,那么即使这样做也很有限。我可能会发现自己经常重复cont
  • 第二,它需要更改源代码。您需要记住在将任何代码提交到版本控制之前删除所有breakpoint()命令,必须在切换分支之前删除它们,等等。我有时发现我想使用调试器来比较两个分支之间的测试运行,并且每次都必须编辑源代码以添加一个断点,这会使操作变得相当慢,而且容易出错。我什至可能要在我正在调用的库中添加一个断点,在这种情况下,我正在编辑的文件甚至可能不在我的git存储库中,而是在我的conda环境中的某个深处,这增加了忘记删除它的风险。以我的愚见,编辑文件以添加断点是很丑的。

要以交互方式添加和删除断点而无需编辑任何源文件,可以按如下方式调用pytest(在bash shell中):

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

-s标志在这里至关重要,因为它可以防止pytest与stdin和stdout发生混乱,并且在调试器中运行时,pytest将无法与stdin和stdout发生混乱,并且一切都会出错。对于不同的外壳,确切的调用语法将有所不同。

答案 6 :(得分:0)

只需使用:pytest --trace test_your_test.py。 这将在测试开始时调用 Python 调试器