我试图编写一段Python代码的单元测试,该代码在特定条件下通过logger.warn('...')
发出警告。我如何断言此警告已被记录?我注意到assertLogged
直到至少Python 3.4才可用,不幸的是我在2.7。Python 2.7单元测试:Assert Logger警告抛出
10
A
回答
2
在您的单元测试设置中,添加一个记录处理程序,用于缓存记录,并在拆卸过程中将其删除。您可以将其用作基准a couple of utility classes, TestHandler
and Matcher
,它们是Python测试基础结构的一部分。 (链接是Python的默认分支,但这些类应该可以在其他Python版本中使用)。有关如何使用这些类的信息,请参阅this post。
2
Python 3.4添加到单元测试的确切功能。请参阅TestCase.assertLogs。这个API是很容易使用:
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'])
现在,这个问题被标记python2.7
,但它会显示在搜索类似的标题python + unittest + logging
。它是很容易回端口功能来Python2.7,所以这里是:
# 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)
现在在你的单元测试模块,你可以使用这个类:
#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的单元测试案例
- 2. 如何将单元测试与assert()
- 3. Python:对象抛出参数警告
- 4. 当从1.5迁移到1.7时出现单元测试警告
- 5. 单元测试课 - 抛出错误吗?
- 6. 单元测试抛出ObjectDisposedException与ObjectContext
- 7. 警告测试
- 8. Python单元测试HTML报告
- 9. Python单元测试以失败告终
- 10. Angular 2材料在业障测试中抛出警告
- 11. 如何用Python的unittest测试一个警告是否被抛出?
- 12. mkdir()抛出警告消息
- 13. QCoreApplication中的ASSERT失败:简单的QT单元测试失败?
- 14. shell_exec抛出警告php
- 15. 硒RC测试+单元测试抛出一个赛格故障
- 16. ASP.NET MVC 3测试版:TryUpdateModel在单元测试中抛出NullreferenceException
- 17. 在JavaScript中“抛出”警告?
- 18. 单元测试101 - 从我的单元内抛出异常
- 19. Python的单元测试报告通过测试
- 20. Python - 单元测试
- 21. Python单元测试
- 22. Redux警告只出现在测试中
- 23. 单元测试/ Python中
- 24. 如何在Python参数化setUpClass()(2.7)单元测试
- 25. Python单元测试突然退出
- 26. assert vs ==在Python中测试代码?
- 27. 可以在PHPUnit中测试单元测试的日志警告吗?
- 28. HttpContextBaseExtensions.GetOwinContext在尝试运行时抛出NullReferenceException单元测试
- 29. VS2010中的单元测试3.5项目会产生CS1685警告
- 30. C#单元测试警告而不是失败