110 votes

Comment vérifier un message de journal lorsque je teste du code Python sous nez ?

J'essaie d'écrire un test unitaire simple qui vérifiera que, sous une certaine condition, une classe de mon application enregistrera une erreur via l'API de journalisation standard. Je n'arrive pas à trouver la façon la plus propre de tester cette situation.

Je sais que nose capture déjà des données de journalisation par le biais de son plugin de journalisation, mais cela semble être conçu comme une aide au rapport et au débogage pour les tests qui échouent.

Je vois deux façons de procéder :

  • Mocker le module de journalisation, soit de manière fragmentaire (mymodule.logging = mockloggingmodule), soit à l'aide d'une bibliothèque de mockage appropriée.
  • Écrire ou utiliser un plugin nose existant pour capturer la sortie et la vérifier.

Si j'opte pour la première approche, j'aimerais savoir quelle est la manière la plus propre de réinitialiser l'état global à ce qu'il était avant que je ne mocke le module de logging.

J'attends avec impatience vos conseils et astuces sur ce sujet...

0voto

Taha Jahangir Points 1317

En ExpectLog implémentée dans tornado est une grande utilité :

with ExpectLog('channel', 'message regex'):
    do_it()

http://tornado.readthedocs.org/en/latest/_modules/tornado/testing.html#ExpectLog

0voto

twildfarmer Points 201

En lien avec la réponse de @Reef, j'ai essayé le code ci-dessous. Il fonctionne bien pour moi à la fois pour Python 2.7 (si vous installez simulacre ) et pour Python 3.4.

"""
Demo using a mock to test logging output.
"""

import logging
try:
    import unittest
except ImportError:
    import unittest2 as unittest

try:
    # Python >= 3.3
    from unittest.mock import Mock, patch
except ImportError:
    from mock import Mock, patch

logging.basicConfig()
LOG=logging.getLogger("(logger under test)")

class TestLoggingOutput(unittest.TestCase):
    """ Demo using Mock to test logging INPUT. That is, it tests what
    parameters were used to invoke the logging method, while still
    allowing actual logger to execute normally.

    """
    def test_logger_log(self):
        """Check for Logger.log call."""
        original_logger = LOG
        patched_log = patch('__main__.LOG.log',
                            side_effect=original_logger.log).start()

        log_msg = 'My log msg.'
        level = logging.ERROR
        LOG.log(level, log_msg)

        # call_args is a tuple of positional and kwargs of the last call
        # to the mocked function.
        # Also consider using call_args_list
        # See: https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_args
        expected = (level, log_msg)
        self.assertEqual(expected, patched_log.call_args[0])

if __name__ == '__main__':
    unittest.main()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X