如何使用%debug调查Python单元测试失败?

如何使用%debug调查Python单元测试失败?,python,unit-testing,ipython,Python,Unit Testing,Ipython,如何从IPython中运行单个Python并使用%debug来调查断言失败的站点 具体来说,我想要这个魔法 $ ipython In [1]: def broken(): ...: DOESNOTEXIST ...: In [2]: broken() --------------------------------------------------------------------------- NameError

如何从IPython中运行单个Python并使用
%debug
来调查断言失败的站点

具体来说,我想要这个魔法

$ ipython
In [1]: def broken():
   ...:     DOESNOTEXIST
   ...:    

In [2]: broken()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-38dbcef999e4> in <module>()
----> 1 broken()

<ipython-input-1-42074db4a06b> in broken()
      1 def broken():
----> 2     DOESNOTEXIST
      3 

NameError: name 'DOESNOTEXIST' is not defined

In [3]: %debug
> <ipython-input-1-42074db4a06b>(2)broken()
      1 def broken():
----> 2     DOESNOTEXIST
      3 

ipdb> # Rock on
…其中,在失败时,运行
%debug
会将我带到某个测试用例失败的
raise

似乎模块接受了异常(正如人们所期望的那样),而
--failfast
标志不会将其抛出。我知道我可以实例化测试对象,然后对其手动调用
setUp()
,等等。但这似乎有点愚蠢,令人痛苦。我不想设置断点。

使用testrunner

我建议您使用pytest ipdb插件安装。您应该能够使用--ipdb标志以类似的方式运行它,以便在测试中发生异常时访问ipdb调试器

pip install git+git://github.com/mverteuil/pytest-ipdb.git
然后

或从命令行:

py.test --ipdb some/path/to/brokenness.py
此外,如果您出于某种原因不喜欢pytest,那么可以使用nose和plugin来存档相同的结果。

看一看运行情况。这可以通过命令行在ipython或jupyter笔记本中单独运行

> pip install nose
在包含测试文件的包目录中,运行:

> nosetests --pdb
这将在所有现有目录和子目录中自动找到预先添加的测试模块
test
。或者,您可以在单独的文件上运行它:

> nosetests test_filename.py --pdb
import nose.tools as nt

def test():
    # Some test code
    return 1

nt.assert_equal(test(), 2)
还有一种方法可以使用
ipdb

nose
对于在ipython/jupyter会话中运行测试特别有用。因此,您可以选择在会话内运行测试,而无需创建单独的文件:

> nosetests test_filename.py --pdb
import nose.tools as nt

def test():
    # Some test code
    return 1

nt.assert_equal(test(), 2)
输出

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-16-edbfc78f9c45> in <module>()
      5     return 1
      6 
----> 7 nt.assert_equal(test(), 2)

C:\Anaconda3\envs\betalab\lib\unittest\case.py in assertEqual(self, first, second, msg)
    818         """
    819         assertion_func = self._getAssertEqualityFunc(first, second)
--> 820         assertion_func(first, second, msg=msg)
    821 
    822     def assertNotEqual(self, first, second, msg=None):

C:\Anaconda3\envs\betalab\lib\unittest\case.py in _baseAssertEqual(self, first, second, msg)
    811             standardMsg = '%s != %s' % _common_shorten_repr(first, second)
    812             msg = self._formatMessage(msg, standardMsg)
--> 813             raise self.failureException(msg)
    814 
    815     def assertEqual(self, first, second, msg=None):

AssertionError: 1 != 2
---------------------------------------------------------------------------
AssertionError回溯(上次最近的调用)
在()
5返回1
6.
---->7 nt.assert_equal(test(),2)
assertEqual中的C:\Anaconda3\envs\betalab\lib\unittest\case.py(self、first、second、msg)
818         """
819断言\u func=self.\u getAssertEqualityFunc(第一,第二)
-->820断言函数(第一,第二,msg=msg)
821
822 def assertNotEqual(自身、第一个、第二个,消息=None):
C:\Anaconda3\envs\betalab\lib\unittest\case.py in_baseAssertEqual(self,first,second,msg)
811 standardMsg='%s!=%s%\u common\u shorten\u repr(第一、第二)
812 msg=self.\u formatMessage(msg,standardMsg)
-->813提升自失效异常(msg)
814
815 def assertEqual(自我、第一、第二、消息=无):
断言错误:1!=2

我也很乐意采用一种解决方案,在这种解决方案中,我只能在出现故障时才被放入IPython。事实上,更令人高兴的是,只需从CLI运行,并在错误的断言上获得一个IPython友好的调试器就可以了。您可以使用
nose
在IPython中运行测试。来自nose文档:Nose在过去几年一直处于维修模式,如果没有新的人员/团队接管维修人员,它可能会停止。新项目应该考虑使用NoSe2、Py.Testor,或者仅仅是UnTest/UnestTest2。“它对于UNITTEST来说是很好的。如果您愿意,可以尝试<代码> NoSe2< /代码>。<代码> PyTest将是最好的,但它还不支持会话测试。