【问题标题】:How to use pdb.set_trace() in a Django unittest?如何在 Django 单元测试中使用 pdb.set_trace()?
【发布时间】:2013-06-17 09:28:56
【问题描述】:

我想像调试任何其他 Python 代码一样调试 Django TestCase:只需调用 pdb.set_trace(),然后进入交互式会话。当我这样做时,我什么都看不到,因为测试是在不同的过程中运行的。我使用的是django-discover-runner,但我猜这适用于默认的 Django 测试运行器。

问题:

是否可以在使用django-discover-runner 时进入pdb 会话?a) 每次错误/失败时,和/或 b) 仅当我在测试代码中调用pdb.set_trace() 时?

一些研究:

This answer 解释说 Django 创建了另一个进程,并建议使用对rpdb2 debugger 的调用,这是winpdb 的一部分,但我不想使用winpdb,我宁愿使用ipdb .

This answer 通过运行如下测试命令解决了django-nose 的问题:./manage.py test -- -s,但该选项不适用于django-discover-runner。

This answer 表明我可以用ipython 做到这一点:

In [9]: %pdb
Automatic pdb calling has been turned ON

这似乎是一个潜在的选择,但每次运行测试时启动 ipython 似乎有点麻烦。

最后,this answer 表明nose 带有一个--pdb 标志,在错误时会下降到pdb,这就是我想要的。切换到django-nose 测试运行器是我唯一的选择吗?

我在django-discover-runner 的内置帮助中没有看到任何选项:

$ python manage.py help test --settings=settings.test
Usage: manage.py test [options] [appname ...]

Runs the test suite for the specified applications, or the entire site if no apps are specified.

Options:
  -v VERBOSITY, --verbosity=VERBOSITY
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=verbose output, 3=very verbose output
  --settings=SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be
                        used.
  --pythonpath=PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Print traceback on exception
  --noinput             Tells Django to NOT prompt the user for input of any
                        kind.
  --failfast            Tells Django to stop running the test suite after
                        first failed test.
  --testrunner=TESTRUNNER
                        Tells Django to use specified test runner class
                        instead of the one specified by the TEST_RUNNER
                        setting.
  --liveserver=LIVESERVER
                        Overrides the default address where the live server
                        (used with LiveServerTestCase) is expected to run
                        from. The default value is localhost:8081.
  -t TOP_LEVEL, --top-level-directory=TOP_LEVEL
                        Top level of project for unittest discovery.
  -p PATTERN, --pattern=PATTERN
                        The test matching pattern. Defaults to test*.py.
  --version             show program's version number and exit
  -h, --help            show this help message and exit

【问题讨论】:

    标签: django debugging django-testing pdb


    【解决方案1】:

    Django 不在单独的进程中运行测试;声称它确实的链接答案是完全错误的。 (最接近的是用于 Selenium 测试的 LiveServerTestCase,它启动了一个单独的线程来运行开发服务器,但这仍然不是一个单独的进程,它不会阻止使用 pdb)。您应该能够在测试(或测试代码)的任何位置插入 import pdb; pdb.set_trace() 并获得可用的 pdb 提示。我从来没有遇到过这个问题,我只是在一个新的项目中用 Django 1.5.1 和 django-discover-runner 1.0 再次验证了它。如果这对您不起作用,那是由于您项目中的其他原因,而不是由于 Django 或 django-discover-runner。

    Nose 默认捕获所有输出,这会破坏import pdb; pdb.set_trace()。 -s 选项关闭输出捕获。这对于现有的 Django 测试运行器或 django-discover-runner 来说不是必需的,因为它们都没有从一开始就进行输出捕获。

    如果您使用的是 django-discover-runner,我不知道有任何与鼻子的--pdb 选项等效的选项。有一个django-pdb 项目提供了这个功能,但是快速阅读它的代码告诉我,它不能很好地与 django-discover-runner 配合使用;不过,它的代码可能会为您提供一些自己实现此功能的线索。

    FWIW,我个人使用 py.test 和 pytest-django 而不是 django-discover-runner 或 django-nose。即使 py.test 提供了一个像鼻子这样的--pdb 选项,我也不使用它;我经常想在实际错误点之前中断,以便在错误之前逐步执行,所以我通常只插入import pytest; pytest.set_trace()(从pytest导入set_trace相当于nose的-s选项;它在运行 pdb 之前关闭 py.test 的输出捕获),我希望它在代码中,然后在我完成后将其删除。我不觉得这很麻烦。 YMMV。

    【讨论】:

      【解决方案2】:

      尝试使用 ipdb 代替 pdb -

      import ipdb;ipdb.set_trace()
      

      或(适用于鼻子测试跑步者)

      from nose.tools import set_trace;set_trace()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-23
        • 1970-01-01
        • 2013-05-08
        • 2012-05-22
        • 1970-01-01
        • 2023-03-05
        • 2016-11-22
        • 2013-02-19
        相关资源
        最近更新 更多