【问题标题】:Can I debug with python debugger when using py.test somehow?以某种方式使用 py.test 时,我可以使用 python 调试器进行调试吗?
【发布时间】:2011-02-10 08:24:07
【问题描述】:

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

将 pdb.set_trace() 放入代码中不起作用(引发 IOError:在捕获输出时从标准输入读取)。我也尝试过使用 --pdb 选项运行 py.test ,但如果我想探索断言之前发生的事情,这似乎并不能解决问题。当断言失败时它会中断,并且从该行继续意味着终止程序。

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

【问题讨论】:

    标签: python unit-testing pdb


    【解决方案1】:

    这真的很简单:在您想要开始调试代码的位置放置一个assert 0,然后运行测试:

    py.test --pdb 
    

    完成:)

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

    【讨论】:

    • 如果你只想调试断言发生的事情,这很好。如果有一个 py.test.set_trace() 也很好(它将重新启用标准输入并调用 pdb.set_trace() (或类似的)。断言 0 的问题是它不可能(AFAIK)抑制异常并继续使用调试器。调用不改变逻辑流的调试器的方法会更好。
    • 嘿杰森。我明白并同意。应该有一个“py.test.pdb()”或类似的东西,不管有没有“-s”。如果您提出问题,我会尽力实施。
    • 嘿杰森。我刚刚添加了 py.test.set_trace() ,请参阅bitbucket.org/hpk42/py-trunk/changeset/1d7b0838917f,您也许可以使用例如安装开发版本。 “pip install URL”,其中 URL 是此处的 zip 文件:hudson.testrun.org/view/pytest/job/py-trunk-sdist(抱歉,StackOverflow 似乎严重截断了 URL,因此无法粘贴完整的 URL)
    • @Sardathrion 您可以安装pdbpp 以获得更好的体验。
    • @Peque 从那时起我就搬到了pdbpp,因为体验确实更好。 ☺
    【解决方案2】:

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

    【讨论】:

    • 这正是我设置 pdb(而不是 --pdb)的方式。注意:您可以使用“-s”代替“--capture=no”
    • 多年来,不再需要禁用捕获。只需在运行堆栈中的某处添加您的 pdb.set_trace() 语句即可。
    • @JasonR.Coombs 但是ipdb.set_trace() 不起作用或更一般的breakpoint() 可能指向它。使用 -s 仍然有效。
    • 这似乎不再起作用了。在测试代​​码的某处添加一个常规的pdb.set_trace(),然后使用-s 或--capture=no 运行只是像往常一样运行pytest,打印测试摘要,并且永远不会进入调试器。
    • @JasonR.Coombs 我的经验是,如果我没有通过-s,pytest 将通过OSError: pytest: reading from stdin while output is captured! Consider using -s. 的所有测试失败。
    【解决方案3】:

    最简单的方法是使用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()

    【讨论】:

    • import ipdb;ipdb.set_trace()需要小编辑
    【解决方案4】:

    与 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】:

      我对py.test不熟悉,把for unittest,你做以下。也许 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

      【讨论】:

      • 彼得,谢谢你的建议。 python -m pdb 替代方法会引导我完成脚本,但不会调用函数,因此虽然对我的 Python 开发很有用,但我不知道如何使该脚本工作。我提到了 --pdb 选项,但除非有人能想到如何使用它,否则我也无法继续使用它。
      • 我建议阅读 pdb 手册并学习击键。 pdb 将打印下一个将执行的函数。如果您键入“s”,您将进入该功能。如果您键入“n”,这是默认值,您只需转到下一行代码。当你想进入你的“主要”例程时,很可能你正在点击“n”而不是“s”。
      • 这不是 py.test 的工作方式。 py.test 的小而有效的测试代码: def test_arithmetic: assert 2+2==4 这足以进行单元测试。没有“main”例程,只是一个以“test_”开头的函数。如果使用普通 python 运行它,它只会定义 test_arithmetic,而不是运行它。但是 py.test 找到以 test_ 开头的函数并为我运行它们,处理失败的断言等。
      【解决方案6】:

      在不编辑源文件的情况下添加和删除个断点

      虽然您可以通过在代码中添加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 混淆,一切都会出错。对于不同的 shell,确切的调用语法会有所不同。

      【讨论】:

      • 别忘了pip install ipdb
      【解决方案7】:

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

      【讨论】:

        猜你喜欢
        • 2019-05-29
        • 1970-01-01
        • 2021-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-13
        相关资源
        最近更新 更多