如何在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()
等。但这似乎有些愚蠢和痛苦。我不想设置断点。
答案 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