Ich versuche, einen Unit Test für ein Stück Python-Code zu schreiben, der unter bestimmten Bedingungen eine Warnung über logger.warn('...')
auslöst. Wie bestätige ich, dass diese Warnung protokolliert wurde? Mir ist aufgefallen, dass assertLogged
erst ab Python 3.4 verfügbar ist, leider bin ich in 2.7.Python 2.7 Komponententest: Assert Logger Warnung ausgelöst
Antwort
Fügen Sie in der Konfiguration des Einheitentests einen Protokollierungshandler hinzu, der Datensätze puffert und während des Teardowns entfernt. Sie können als Basis a couple of utility classes, TestHandler
and Matcher
verwenden, die Teil der Python-Testinfrastruktur sind. (Der Link ist zu Pythons Standardzweig, aber die Klassen sollten in anderen Python-Versionen verwendbar sein). Informationen zur Verwendung dieser Klassen finden Sie unter this post.
Python 3.4 Hinzugefügt zu Unittest genau diese Funktion. Siehe TestCase.assertLogs. Die API ist wirklich einfach zu bedienen:
with self.assertLogs('foo', level='INFO') as cm:
logging.getLogger('foo').info('first message')
logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
'ERROR:foo.bar:second message'])
Nun ist diese Frage python2.7
markiert, aber es wird sich zeigen, wenn Suche nach ähnlichen Titel für python + unittest + logging
. Und es ist ziemlich einfach zu-Port zurück, die python2.7 verfügen, so ist es hier:
# logger_test.py
# this file contains the base class containing the newly added method
# assertLogs
import collections
import logging
_LoggingWatcher = collections.namedtuple("_LoggingWatcher",
["records", "output"])
class _BaseTestCaseContext(object):
def __init__(self, test_case):
self.test_case = test_case
def _raiseFailure(self, standardMsg):
msg = self.test_case._formatMessage(self.msg, standardMsg)
raise self.test_case.failureException(msg)
class _CapturingHandler(logging.Handler):
"""
A logging handler capturing all (raw and formatted) logging output.
"""
def __init__(self):
logging.Handler.__init__(self)
self.watcher = _LoggingWatcher([], [])
def flush(self):
pass
def emit(self, record):
self.watcher.records.append(record)
msg = self.format(record)
self.watcher.output.append(msg)
class _AssertLogsContext(_BaseTestCaseContext):
"""A context manager used to implement TestCase.assertLogs()."""
LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s"
def __init__(self, test_case, logger_name, level):
_BaseTestCaseContext.__init__(self, test_case)
self.logger_name = logger_name
if level:
self.level = logging._levelNames.get(level, level)
else:
self.level = logging.INFO
self.msg = None
def __enter__(self):
if isinstance(self.logger_name, logging.Logger):
logger = self.logger = self.logger_name
else:
logger = self.logger = logging.getLogger(self.logger_name)
formatter = logging.Formatter(self.LOGGING_FORMAT)
handler = _CapturingHandler()
handler.setFormatter(formatter)
self.watcher = handler.watcher
self.old_handlers = logger.handlers[:]
self.old_level = logger.level
self.old_propagate = logger.propagate
logger.handlers = [handler]
logger.setLevel(self.level)
logger.propagate = False
return handler.watcher
def __exit__(self, exc_type, exc_value, tb):
self.logger.handlers = self.old_handlers
self.logger.propagate = self.old_propagate
self.logger.setLevel(self.old_level)
if exc_type is not None:
# let unexpected exceptions pass through
return False
if len(self.watcher.records) == 0:
self._raiseFailure(
"no logs of level {} or higher triggered on {}"
.format(logging.getLevelName(self.level), self.logger.name))
class LogTestCase(unittest.TestCase):
def assertLogs(self, logger=None, level=None):
"""Fail unless a log message of level *level* or higher is emitted
on *logger_name* or its children. If omitted, *level* defaults to
INFO and *logger* defaults to the root logger.
This method must be used as a context manager, and will yield
a recording object with two attributes: `output` and `records`.
At the end of the context manager, the `output` attribute will
be a list of the matching formatted log messages and the
`records` attribute will be a list of the corresponding LogRecord
objects.
Example::
with self.assertLogs('foo', level='INFO') as cm:
logging.getLogger('foo').info('first message')
logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
'ERROR:foo.bar:second message'])
"""
return _AssertLogsContext(self, logger, level)
Jetzt in Ihrem Komponententests Module Sie diese Klasse verwenden können:
#test_my_module
from logger_test import LogTestCase
class TestMyModule(LogTestCase):
def test_some_feature(self):
with self.assertLogs('foo', level='INFO') as cm:
logging.getLogger('foo').info('first message')
logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
'ERROR:foo.bar:second message'])
- 1. Assert-Ausnahme ausgelöst in MUnit, Mulesoft
- 2. Assert Fehler wird ausgelöst, wenn Piktoons3 spotten
- 3. ansible Kryptographie mit SCL Python 2.7 in Centos Warnung 6
- 4. Python Logger funktioniert nicht
- 5. Python Logger dynamischer Dateiname
- 6. Naming Python Logger
- 7. Disable Python Logger Ausgabe
- 8. Python Sklearn - Warnung Warnung
- 9. Komponententest für innere Ausnahmen
- 10. Python 2.7 sqlite3 Logging
- 11. Ttk on python 2.7
- 12. Super in Python 2.7
- 13. Drucken in Python 2.7
- 14. cx_Oracle und Python 2.7
- 15. Python 2.7 os.path.isfile
- 16. findall() Verhalten (Python 2.7)
- 17. mod_python für python 2.7
- 18. Abteilung in Python 2.7
- 19. Bluetooth für Python 2.7?
- 20. Python 2.7 Tkinter Code
- 21. Python 2.7 print() Fehler
- 22. Aktivieren Python 2.7
- 23. Zyklusdaten in Python 2.7
- 24. Pafy - Python 2.7
- 25. Dateipfad in Python 2.7
- 26. Python 2.7 Kleinbuchstaben
- 27. Multithread in Python 2.7?
- 28. Python 2.7 unbekannt Syntaxfehler
- 29. Variierender Titel Python 2.7
- 30. Code-Fehler-Python 2.7