用pytest测试日志输出

lau*_*tta 6 python testing logging unit-testing pytest

我正在尝试使用pytest编写测试,该测试将检查特定功能是否在需要时向日志写警告。例如:

在module.py中:

import logging
LOGGER = logging.getLogger(__name__)

def run_function():
    if something_bad_happens:
        LOGGER.warning('Something bad happened!')
Run Code Online (Sandbox Code Playgroud)

在test_module.py中:

import logging
from module import run_function

LOGGER = logging.getLogger(__name__)

def test_func():
    LOGGER.info('Testing now.')
    run_function()
    ~ somehow get the stdout/log of run_function() ~
    assert 'Something bad happened!' in output
Run Code Online (Sandbox Code Playgroud)

I have seen that you can supposedly get the log or the stdout/stderr with pytest by passing capsys or caplog as an argument to the test, and then using either capsus.readouterr() or caplog.records to access the output.

However, when I try those methods, I only see "Testing now.", and not "Something bad happened!". It seems like the logging output that is happening within the call to run_function() is not accessible from test_func()?

The same thing happens if I try a more direct method, such as sys.stdout.getvalue(). Which is confusing, because run_function() is writing to the terminal, so I would think that would be accessible from stdout...?

Basically, does anyone know how I can access that 'Something bad happened!' from within test_func()?

小智 24

test_module.py 应该是这样的:

import logging
from module import run_function

LOGGER = logging.getLogger(__name__)

def test_func(caplog):
    with caplog.at_level(logging.WARNING):
        run_function()
    assert 'Something bad happened!' in caplog.text
Run Code Online (Sandbox Code Playgroud)

或者:

import logging
from module import run_function

LOGGER = logging.getLogger(__name__)

def test_func(caplog):
    caplog.set_level(logging.WARNING):
    run_function()
    assert 'Something bad happened!' in caplog.text
Run Code Online (Sandbox Code Playgroud)

pytest 捕获日志的文档在这里

  • 正如 @ssoler 的回答中正确提到的,在您的记录器设置中,请确保 logger.propagate=True (4认同)

lau*_*tta 7

我不知道为什么以前尝试过这种方法不起作用,但是这种解决方案现在对我有用:

在test_module.py中:

import logging
from module import run_function

LOGGER = logging.getLogger(__name__)

def test_func(caplog):
    LOGGER.info('Testing now.')
    run_function()
    assert 'Something bad happened!' in caplog.text
Run Code Online (Sandbox Code Playgroud)

  • 只是在开玩笑,这仍然行不通。 (3认同)
  • @exic 这对我不起作用。请参阅[此问题](/sf/ask/4191318841/)。 (3认同)
  • 正如 @ssoler 的回答中正确提到的,在您的记录器设置中,请确保 logger.propagate=True (2认同)

sso*_*ler 5

在您的日志记录设置中,checkpropagate设置为 True,否则 caplog 处理程序无法看到日志消息。

  • 这是关键问题,谢谢@ssoler (2认同)