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()
Était-ce utile?

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

améliorations du cadre de test tierce partie semble généralement inclure la fonction (nose et nose2 ont déjà été mentionnés dans d'autres réponses). Un peu plus:

pytest supporte.

pytest --pdb

Ou si vous utilisez absl-py 's absltest au lieu du module unittest:

name_of_test.py --pdb_post_mortem
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top