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

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

logging.basicConfig(level=logging.DEBUG)

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

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

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


当前回答

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

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

其他回答

在我的情况下,我有一个设置文件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。

如果你正在使用pytest,你可以安装超级有用的pytest-mock插件,并定义一个自动使用的会话范围的fixture,可以由env var触发:

# conftest.py

import os
import pytest


@pytest.fixture(autouse=True, scope="session")
def _shut_logger(session_mocker):
    if os.getenv("SHUT_LOGGER", None):
        return session_mocker.patch("foo.logger")

如果你想在2021年或以后考虑这个问题,你可能问错了问题

在现代版本的Django*中,使用开箱即用的配置,测试应该不会在屏幕上产生任何日志记录。因此,如果你在问这个问题,真正的答案可能是“某些东西配置错误”。这是因为(默认情况下):

打印日志消息到控制台需要debug为True 测试运行DEBUG=False

因此,如果您使用的记录器与在LOGGING['loggers']中定义的记录器相匹配,并且由“控制台”处理程序处理,那么测试应该不会在屏幕上产生任何日志记录。

如果你在测试中看到了什么,你也

日志记录器的名称与在设置中定义的内容不匹配。日志记录 正在使用DEBUG=True运行测试(需要重写) 已经从控制台处理程序的过滤器中删除了“require_debug_true”。

*现代版本的意思是:2.1及以上,即不古老。

我们使用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,
    ]
    ...

)

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

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