如何在Django unittest中使用pdb.set_trace()?

时间:2013-06-20 13:36:40

标签: django debugging django-testing pdb

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

问题:

是否可以在每次错误/失败时使用pdb a)进入django-discover-runner会话,和/或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

2 个答案:

答案 0 :(得分:20)

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,我不知道有什么等同于nose的--pdb选项。有一个django-pdb项目提供了这个,但是快速阅读它的代码告诉我,它不能很好地与django-discover-runner合作;但是,它的代码可能会为你自己实现这一点提供一些线索。

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

答案 1 :(得分:11)

尝试使用ipdb而不是pdb -

import ipdb;ipdb.set_trace()

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

from nose.tools import set_trace;set_trace()