有没有办法在单元测试失败时自动启动调试器?
现在我只是手动使用pdb.set_trace(),但这非常繁琐,因为我需要每次添加它并在结束时将其取出。
例如:
import unittest
class tests(unittest.TestCase):
def setUp(self):
pass
def test_trigger_pdb(self):
#this is the way I do it now
try:
assert 1==0
except AssertionError:
import pdb
pdb.set_trace()
def test_no_trigger(self):
#this is the way I would like to do it:
a=1
b=2
assert a==b
#magically, pdb would start here
#so that I could inspect the values of a and b
if __name__=='__main__':
#In the documentation the unittest.TestCase has a debug() method
#but I don't understand how to use it
#A=tests()
#A.debug(A)
unittest.main()
答案 0 :(得分:36)
答案 1 :(得分:23)
import unittest
import sys
import pdb
import functools
import traceback
def debug_on(*exceptions):
if not exceptions:
exceptions = (AssertionError, )
def decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
try:
return f(*args, **kwargs)
except exceptions:
info = sys.exc_info()
traceback.print_exception(*info)
pdb.post_mortem(info[2])
return wrapper
return decorator
class tests(unittest.TestCase):
@debug_on()
def test_trigger_pdb(self):
assert 1 == 0
我更正了代码,在异常而不是set_trace上调用post_mortem。
答案 2 :(得分:3)
一个简单的选择是在没有结果收集的情况下运行测试,并让第一个异常崩溃堆栈(用于任意事后处理),例如。
unittest.TextTestResult
另一个选项:在调试测试运行器中覆盖addError
的{{1}}和addFailure
,以便立即进行post_mortem调试(在tearDown()
之前) - 或者用于收集和处理错误和放大器;以先进的方式追溯。
(不需要额外的框架或测试方法的额外装饰器)
基本示例:
import unittest, pdb
class TC(unittest.TestCase):
def testZeroDiv(self):
1 / 0
def debugTestRunner(post_mortem=None):
"""unittest runner doing post mortem debugging on failing tests"""
if post_mortem is None:
post_mortem = pdb.post_mortem
class DebugTestResult(unittest.TextTestResult):
def addError(self, test, err):
# called before tearDown()
traceback.print_exception(*err)
post_mortem(err[2])
super(DebugTestResult, self).addError(test, err)
def addFailure(self, test, err):
traceback.print_exception(*err)
post_mortem(err[2])
super(DebugTestResult, self).addFailure(test, err)
return unittest.TextTestRunner(resultclass=DebugTestResult)
if __name__ == '__main__':
##unittest.main()
unittest.main(testRunner=debugTestRunner())
##unittest.main(testRunner=debugTestRunner(pywin.debugger.post_mortem))
##unittest.findTestCases(__main__).debug()
答案 3 :(得分:0)
要通过apt-get install nose2
将@cmcginty's answer应用于基于Debian的系统上的后继nose 2(recommended by nose),您可以drop into the debugger查看有关失败和错误的信息。调用
nose2
在您的测试目录中。
为此,您需要在主目录中有一个合适的.unittest.cfg
或在项目目录中有unittest.cfg
;它需要包含行
[debugger]
always-on = True
errors-only = False
答案 4 :(得分:0)
这是一个内置的,没有额外模块的解决方案:
import unittest
import sys
import pdb
####################################
def ppdb(e=None):
"""conditional debugging
use with: `if ppdb(): pdb.set_trace()`
"""
return ppdb.enabled
ppdb.enabled = False
###################################
class SomeTest(unittest.TestCase):
def test_success(self):
try:
pass
except Exception, e:
if ppdb(): pdb.set_trace()
raise
def test_fail(self):
try:
res = 1/0
#note: a `nosetests --pdb` run will stop after any exception
#even one without try/except and ppdb() does not not modify that.
except Exception, e:
if ppdb(): pdb.set_trace()
raise
if __name__ == '__main__':
#conditional debugging, but not in nosetests
if "--pdb" in sys.argv:
print "pdb requested"
ppdb.enabled = not sys.argv[0].endswith("nosetests")
sys.argv.remove("--pdb")
unittest.main()
用python myunittest.py --pdb
调用它,它将停止。否则就不会。
答案 5 :(得分:0)