Kry*_*ski 21 python testing django unit-testing python-unittest
我想确保我的代码中的某个条件导致将日志消息写入django日志.我如何使用Django单元测试框架?
有没有我可以检查已记录消息的地方,类似于我如何查看已发送的电子邮件?我的单元测试延伸django.test.TestCase.
Sim*_*ser 36
使用该mock模块模拟日志记录模块或记录器对象.完成后,检查调用日志记录函数的参数.
例如,如果您的代码如下所示:
import logging
logger = logging.getLogger('my_logger')
logger.error("Your log message here")
Run Code Online (Sandbox Code Playgroud)
它看起来像:
from unittest.mock import patch # For python 2.x use from mock import patch
@patch('this.is.my.module.logger')
def test_check_logging_message(self, mock_logger):
mock_logger.error.assert_called_with("Your log message here")
Run Code Online (Sandbox Code Playgroud)
您还可以使用assertLogs从django.test.TestCase
当你编码是
import logging
logger = logging.getLogger('my_logger')
def code_that_throws_error_log():
logger.error("Your log message here")
Run Code Online (Sandbox Code Playgroud)
这是测试代码。
with self.assertLogs(logger='my_logger', level='ERROR') as cm:
code_that_throws_error_log()
self.assertIn(
"ERROR:your.module:Your log message here",
cm.output
)
Run Code Online (Sandbox Code Playgroud)
这样可以避免仅为日志打补丁。
模拟记录器对象的常见方法(参见精彩的Simeon Visser的答案)有点棘手,因为它需要测试来模拟它所做的所有地方的记录.如果日志记录来自多个模块,或者是您不拥有的代码,则这很尴尬.如果日志记录来自更改名称,那么它将破坏您的测试.
精彩的' testfixtures '软件包包括添加日志记录处理程序的工具,该处理程序捕获所有生成的日志消息,无论它们来自何处.稍后可以通过测试询问捕获的消息.最简单的形式:
假设代码测试,记录:
import logging
logger = logging.getLogger()
logger.info('a message')
logger.error('an error')
Run Code Online (Sandbox Code Playgroud)
对此的测试将是:
from testfixtures import LogCapture
with LogCapture() as l:
call_code_under_test()
l.check(
('root', 'INFO', 'a message'),
('root', 'ERROR', 'an error'),
)
Run Code Online (Sandbox Code Playgroud)
"root"一词表示日志记录是通过使用logging.getLogger()(即没有args)创建的记录器发送的.如果将arg传递给getLogger(__name__常规),则将使用该arg代替"root".
测试不关心哪个模块创建了日志记录.它可能是我们的测试代码调用的子模块,包括第三方代码.
测试断言生成的实际日志消息,而不是模拟技术,该模型断言传递的args.如果logging.info调用使用'%s'格式字符串以及您自己不扩展的其他参数(例如,使用logging.info('total=%s', len(items))而不是logging.info('total=%s' % len(items)),您应该使用它们,这将是不同的.这不是额外的工作,并允许假设的未来日志记录聚合服务,如'Sentry'能够正常工作 - 他们可以看到"total = 12"和"total = 43"是同一条日志消息的两个实例.这就是为什么pylint会警告后一种形式的logging.info呼叫.)
LogCapture包括用于日志过滤等的工具.它的父级'testfixtures'包由Chris Withers编写,另一个出色的包包,包括许多其他有用的测试工具.文档在这里:http://pythonhosted.org/testfixtures/logging.html
Django 有一个很好的上下文管理器函数,称为patch_logger.
from django.test.utils import patch_logger
Run Code Online (Sandbox Code Playgroud)
然后在您的测试用例中:
with patch_logger('logger_name', 'error') as cm:
self.assertIn("Error message", cm)
Run Code Online (Sandbox Code Playgroud)
在哪里:
logger_name 是记录器名称(废话)error 是日志级别cm 是所有日志消息的列表更多细节:
https://github.com/django/django/blob/2.1/django/test/utils.py#L638
它应该适用于 django < 2.0,独立于 python 版本(只要它受 dj 支持)