我正在使用一个简单的基于单元测试的测试运行器来测试我的Django应用程序。

我的应用程序本身被配置为在settings.py中使用一个基本的日志记录器:

logging.basicConfig(level=logging.DEBUG)

并在我的应用程序代码使用:

logger = logging.getLogger(__name__)
logger.setLevel(getattr(settings, 'LOG_LEVEL', logging.DEBUG))

但是,在运行单元测试时,我想禁用日志记录,这样它就不会使测试结果输出混乱。有没有一种简单的方法以全局方式关闭日志记录,这样当我运行测试时,特定于应用程序的日志记录器就不会把东西写到控制台了?


当前回答

logging.disable(logging.CRITICAL)

将禁用级别小于或等于CRITICAL的所有日志调用。可以重新启用日志记录

logging.disable(logging.NOTSET)

其他回答

我们使用structlog,禁用它有点复杂:

from structlog import DropEvent

def disable_logging_in_tests(_, __, event_dict):
    if len(sys.argv) > 1 and sys.argv[1] == 'test':
        raise DropEvent
    return event_dict


structlog.configure(
    processors=[
        ...
        disable_logging_in_tests,
    ]
    ...

)

使用unittest.mock.patch方法有一些漂亮而干净的方法来暂停测试中的登录。

foo.py:

import logging


logger = logging.getLogger(__name__)

def bar():
    logger.error('There is some error output here!')
    return True

tests.py:

from unittest import mock, TestCase
from foo import bar


class FooBarTestCase(TestCase):
    @mock.patch('foo.logger', mock.Mock())
    def test_bar(self):
        self.assertTrue(bar())

而python3 -m unittest测试将不会产生日志输出。

如果你正在使用pytest:

由于pytest捕获日志消息,并且仅在失败的测试中显示它们,因此通常不希望禁用任何日志记录。相反,使用一个单独的settings.py文件进行测试(例如test_settings.py),并添加到它:

LOGGING_CONFIG = None

这告诉Django完全跳过日志配置。LOGGING设置将被忽略,并可以从设置中删除。

使用这种方法,您不会获得通过测试的任何日志记录,而会获得失败测试的所有可用日志记录。

测试将使用pytest设置的日志运行。它可以在pytest设置中根据您的喜好进行配置(例如,tox.ini)。要包含调试级别的日志消息,请使用log_level = debug(或相应的命令行参数)。

如果你有不同的初始化器模块用于测试,开发和生产,那么你可以禁用任何东西或重定向初始化器。我有local。py, test。py和production。py,它们都继承自common。y

py执行所有主要配置,包括以下代码段:

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
    'django.server': {
        '()': 'django.utils.log.ServerFormatter',
        'format': '[%(server_time)s] %(message)s',
    },
    'verbose': {
        'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
    },
    'simple': {
        'format': '%(levelname)s %(message)s'
    },
},
'filters': {
    'require_debug_true': {
        '()': 'django.utils.log.RequireDebugTrue',
    },
},
'handlers': {
    'django.server': {
        'level': 'INFO',
        'class': 'logging.StreamHandler',
        'formatter': 'django.server',
    },
    'console': {
        'level': 'DEBUG',
        'class': 'logging.StreamHandler',
        'formatter': 'simple'
    },
    'mail_admins': {
        'level': 'ERROR',
        'class': 'django.utils.log.AdminEmailHandler'
    }
},
'loggers': {
    'django': {
        'handlers': ['console'],
        'level': 'INFO',
        'propagate': True,
    },
    'celery.tasks': {
        'handlers': ['console'],
        'level': 'DEBUG',
        'propagate': True,
    },
    'django.server': {
        'handlers': ['django.server'],
        'level': 'INFO',
        'propagate': False,
    },
}

然后在test.py中,我有这个:

console_logger = Common.LOGGING.get('handlers').get('console')
console_logger['class'] = 'logging.FileHandler
console_logger['filename'] = './unitest.log

这将控制台处理程序替换为FileHandler,这意味着仍然可以获得日志记录,但我不必触及生产代码库。

logging.disable(logging.CRITICAL)

将禁用级别小于或等于CRITICAL的所有日志调用。可以重新启用日志记录

logging.disable(logging.NOTSET)