如何使用%debug来研究Python unittest失败?

时间:2017-05-08 19:18:52

标签: python unit-testing ipython

如何在IPython中运行单个Python unittest并使用%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

......开始单元测试时可用......

In [4]: %run -m unittest some/path/to/brokenness.py

...如果失败,运行%debug会将我带到raise某个测试用例失败的地方。

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

2 个答案:

答案 0 :(得分:1)

使用testrunner

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

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

然后

In [1]: %run -m pytest --ipdb some/path/to/brokenness.py

或从命令行:

py.test --ipdb some/path/to/brokenness.py

另外,如果您因某种原因不喜欢pytest,可以使用nose和nose-ipdb插件存档相同的结果。

答案 1 :(得分:1)

看看正在运行的nose。这可以通过命令行在ipython或jupyter笔记本中单独运行。

> pip install nose

在包含测试文件的包目录中,运行:

> nosetests --pdb

这将自动在所有当前和子目录中找到前置test_的测试模块。或者,您可以在单独的文件上运行它:

> nosetests test_filename.py --pdb

还有一个plugin可以使用ipdb

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

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