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

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

logging.basicConfig(level=logging.DEBUG)

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

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

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


当前回答

如果你正在使用pytest:

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

LOGGING_CONFIG = None

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

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

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

其他回答

在我的情况下,我有一个设置文件settings/test.py专门为测试目的创建,下面是它的样子:

from .base import *

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'test_db'
    }
}

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.MD5PasswordHasher',
)

LOGGING = {}

我放了一个环境变量DJANGO_SETTINGS_MODULE=settings。测试到/etc/environment。

有时你想要日志,有时不想要。我在settings。py中有这段代码

import sys

if '--no-logs' in sys.argv:
    print('> Disabling logging levels of CRITICAL and below.')
    sys.argv.remove('--no-logs')
    logging.disable(logging.CRITICAL)

所以如果你使用——no-logs选项运行测试,你将只得到关键日志:

$ python ./manage.py tests --no-logs
> Disabling logging levels of CRITICAL and below.

如果您想加快持续集成流的测试,这是非常有用的。

我使用了一个简单的方法装饰器来禁用特定测试方法中的日志记录。

def disable_logging(f):

    def wrapper(*args):
        logging.disable(logging.CRITICAL)
        result = f(*args)
        logging.disable(logging.NOTSET)

        return result

    return wrapper

然后我在下面的例子中使用它:

class ScenarioTestCase(TestCase):

    @disable_logging
    test_scenario(self):
        pass

禁用整个模块的日志记录:

import logging


def setUpModule():
    """Disable logging while doing these tests."""
    logging.disable()


def tearDownModule():
    """Re-enable logging after doing these tests."""
    logging.disable(logging.NOTSET)


class TestFoo(unittest.TestCase):

    def test_foo(self):
        pass

我的一些测试包含关于日志输出的断言,因此更改日志级别会破坏它们。相反,我改变了Django LOGGING设置,在运行测试时使用NullHandler:

if 'test' in sys.argv:
    _LOG_HANDLERS = ['null']
else:
    _LOG_HANDLERS = ['console']
    
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'handlers': {
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple',
        },
    },
    'loggers': {
        'django': {
            'handlers': _LOG_HANDLERS,
            'propagate': True,
            'level': 'INFO',
        },
    }
}