Unité Python Test: Exécution automatique du débogueur lorsqu'un test échoue
-
10-10-2019 - |
Question
Est-il possible de démarrer automatiquement le débogueur au point où une défaillance unittest?
En ce moment je suis juste en utilisant pdb.set_trace () manuellement, mais cela est très ennuyeux que je dois l'ajouter à chaque fois et le prendre à la fin.
Par exemple:
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()
La solution
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
Je corrige le code à l'appel post_mortem à l'exception au lieu de set_trace.
Autres conseils
Je pense que ce que vous cherchez est nez. Il fonctionne comme un coureur de test pour unittest .
Vous pouvez tomber dans le débogueur sur les erreurs, avec la commande suivante:
nosetests --pdb
Une option simple est de simplement exécuter les essais sans la collecte des résultats et de laisser le premier crash d'exception sur la pile (pour le traitement post-mortem arbitraire) par par exemple.
unittest.findTestCases(__main__).debug()
Une autre option. Remplacer unittest.TextTestResult
de addError
et addFailure
dans un lanceur de test de débogage pour le débogage post_mortem immédiate (avant tearDown()
) - ou pour la collecte et la gestion des erreurs et retraçage de manière avancée
(Ne nécessite pas de cadres supplémentaires ou un décorateur d'appoint pour les méthodes d'essai)
Exemple de base:
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()
Voici un module, pas supplémentaire intégré, solution:
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()
appeler avec python myunittest.py --pdb
et il arrêtera. Sinon, il ne sera pas.
Pour appliquer @ réponse cmcginty au successeur nez 2 ( recommandé par le nez disponible sur les systèmes Debian via apt-get install nose2
), vous pouvez goutte dans le débogueur sur les échecs et les erreurs en appelant
nose2
dans votre répertoire de test.
Pour cela, vous devez avoir un .unittest.cfg
approprié dans votre répertoire ou unittest.cfg
dans le répertoire du projet; il doit contenir les lignes
[debugger]
always-on = True
errors-only = False