使用 pytest 测试日志输出

Posted

技术标签:

【中文标题】使用 pytest 测试日志输出【英文标题】:Testing logging output with pytest 【发布时间】:2019-04-07 02:17:43 【问题描述】:

我正在尝试使用 pytest 编写一个测试,以检查特定函数是否在需要时将警告写入日志。例如:

在module.py中:

import logging
LOGGER = logging.getLogger(__name__)

def run_function():
    if something_bad_happens:
        LOGGER.warning('Something bad happened!')

在 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

我已经看到,您可以通过将 capsyscaplog 作为参数传递给测试,然后使用 capsus.readouterr()caplog.records 访问输出。

但是,当我尝试这些方法时,我只看到“正在测试。”,而不是“发生了不好的事情!”。似乎无法从test_func() 访问在对run_function() 的调用中发生的日志记录输出?

如果我尝试更直接的方法,例如sys.stdout.getvalue(),也会发生同样的事情。这令人困惑,因为run_function() 正在写入终端,所以我认为可以从stdout...访问?

基本上,有谁知道我如何访问“发生了不好的事情!”来自test_func()

【问题讨论】:

docs.pytest.org/en/latest/how-to/logging.html 【参考方案1】:

我还想为将来遇到此问题的任何人添加到此线程中。您可能需要使用

@pytest.fixture(autouse=True)

作为测试的装饰器,因此测试可以访问 caplog 固定装置。

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

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

或:

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

pytest 捕获日志的文档是here

【讨论】:

正如@ssoler 的回答中正确提到的那样,在您的记录器设置中,确保 logger.propagate=True【参考方案4】:

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

在 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

【讨论】:

我认为它可能适用于 Python 3.5,但不适用于 3.6 或 3.7。 也许我不明白你在尝试什么,但我使用的是 python3.7 并且我的 caplog.text 包含我期望它包含的内容。 我在做几乎相同的事情,但它不起作用 - 这意味着 caplog.text 是空的。唯一的区别是 run_function() 在我的情况下是 pytest.fixture 中的方法,但这不重要,对吧? @exic 这对我不起作用。见this question。 正如@ssoler 的回答中正确提到的那样,在您的记录器设置中,确保 logger.propagate=True

以上是关于使用 pytest 测试日志输出的主要内容,如果未能解决你的问题,请参考以下文章

pytest中的关联参数化日志及测试报告

pytest 看不到正在测试的函数的日志

自定义 pytest junitxml 失败报告

(二)pytest测试框架

Pytest 在测试后花费的时间最多?

python+pytest接口自动化(14)-接口自动化项目中日志的使用 (使用loguru模块)