在 pytest 测试中记录日志

发布于 2024-10-12 00:59:29 字数 1551 浏览 4 评论 0 原文

我想在测试函数中放置一些日志语句来检查一些状态变量。

我有以下代码片段:

import pytest,os
import logging

logging.basicConfig(level=logging.DEBUG)
mylogger = logging.getLogger()

#############################################################################

def setup_module(module):
    ''' Setup for the entire module '''
    mylogger.info('Inside Setup')
    # Do the actual setup stuff here
    pass

def setup_function(func):
    ''' Setup for test functions '''
    if func == test_one:
        mylogger.info(' Hurray !!')

def test_one():
    ''' Test One '''
    mylogger.info('Inside Test 1')
    #assert 0 == 1
    pass

def test_two():
    ''' Test Two '''
    mylogger.info('Inside Test 2')
    pass

if __name__ == '__main__':
    mylogger.info(' About to start the tests ')
    pytest.main(args=[os.path.abspath(__file__)])
    mylogger.info(' Done executing the tests ')

我得到以下输出:

[bmaryada-mbp:/Users/bmaryada/dev/platform/main/proto/tests/tpch $]python minitest.py
INFO:root: About to start the tests 
======================================================== test session starts =========================================================
platform darwin -- Python 2.6.2 -- pytest-2.0.0
collected 2 items 

minitest.py ..

====================================================== 2 passed in 0.01 seconds ======================================================
INFO:root: Done executing the tests 

请注意,只有来自 '__name__ == __main__' 块的日志消息会传输到控制台。

有没有办法强制 pytest 也从测试方法将日志记录发送到控制台?

I would like to put some logging statements within test function to examine some state variables.

I have the following code snippet:

import pytest,os
import logging

logging.basicConfig(level=logging.DEBUG)
mylogger = logging.getLogger()

#############################################################################

def setup_module(module):
    ''' Setup for the entire module '''
    mylogger.info('Inside Setup')
    # Do the actual setup stuff here
    pass

def setup_function(func):
    ''' Setup for test functions '''
    if func == test_one:
        mylogger.info(' Hurray !!')

def test_one():
    ''' Test One '''
    mylogger.info('Inside Test 1')
    #assert 0 == 1
    pass

def test_two():
    ''' Test Two '''
    mylogger.info('Inside Test 2')
    pass

if __name__ == '__main__':
    mylogger.info(' About to start the tests ')
    pytest.main(args=[os.path.abspath(__file__)])
    mylogger.info(' Done executing the tests ')

I get the following output:

[bmaryada-mbp:/Users/bmaryada/dev/platform/main/proto/tests/tpch $]python minitest.py
INFO:root: About to start the tests 
======================================================== test session starts =========================================================
platform darwin -- Python 2.6.2 -- pytest-2.0.0
collected 2 items 

minitest.py ..

====================================================== 2 passed in 0.01 seconds ======================================================
INFO:root: Done executing the tests 

Notice that only the logging messages from the '__name__ == __main__' block get transmitted to the console.

Is there a way to force pytest to emit logging to console from test methods as well?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

想念有你 2024-10-19 00:59:29

从 3.3 版本开始,pytest 支持实时日志记录,这意味着测试中发出的所有日志记录都将立即打印到终端。该功能记录在实时日志部分。默认情况下禁用实时记录;要启用它,请在 pyproject.toml1pytest.ini2 中设置 log_cli = 1 配置。实时日志记录支持发送到终端和文件;相关选项允许记录自定义:

终端:

  • log_cli_level
  • log_cli_format
  • log_cli_date_format

文件:

  • log_file
  • log_file_level
  • log_file_format
  • log_file_date_format

正如此评论中的 >Kévin Barré ,可以通过以下方式从命令行覆盖 ini 选项:

-o OVERRIDE_INI, --override-ini=OVERRIDE_INI
       使用“option=value”样式覆盖 ini 选项,例如
        -o xfail_strict=True -o cache_dir=cache

因此,不要在 pytest 中声明 log_cli .ini,您可以简单地调用:

$ pytest -o log_cli=true ...

Examples

用于演示的简单测试文件:

# test_spam.py

import logging

LOGGER = logging.getLogger(__name__)


def test_eggs():
    LOGGER.info('eggs info')
    LOGGER.warning('eggs warning')
    LOGGER.error('eggs error')
    LOGGER.critical('eggs critical')
    assert True

正如您所看到的,不需要额外的配置; pytest 将根据 pytest.ini 中指定的选项或从命令行传递的选项自动设置记录器。

实时记录到终端,INFO 级别,奇特的输出

pyproject.toml 中的配置:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "INFO"
log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"

旧版 pytest.ini 中的相同配置:

[pytest]
log_cli = 1
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_cli_date_format=%Y-%m-%d %H:%M:%S

运行测试:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
2018-08-01 14:33:20 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:33:20 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:33:20 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:33:20 [CRITICAL] eggs critical (test_spam.py:10)
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

实时记录到终端和文件,仅消息和文件终端中的 CRITICAL 级别,pytest.log 文件中的精美输出

pyproject.toml 中的配置:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "CRITICAL"
log_cli_format = "%(message)s"

log_file = "pytest.log"
log_file_level = "DEBUG"
log_file_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_file_date_format = "%Y-%m-%d %H:%M:%S"

旧版 pytest.ini 中的相同配置

[pytest]
log_cli = 1
log_cli_level = CRITICAL
log_cli_format = %(message)s

log_file = pytest.log
log_file_level = DEBUG
log_file_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_file_date_format=%Y-%m-%d %H:%M:%S

测试运行:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
eggs critical
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

$ cat pytest.log
2018-08-01 14:38:09 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:38:09 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:38:09 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:38:09 [CRITICAL] eggs critical (test_spam.py:10)

1 pyproject.toml 自版本 6.0 起受支持,是 IMO 的最佳选择。有关规范,请参阅 PEP 518

2 虽然您也可以在 [tool:pytest] 部分下的 setup.cfg 中配置 pytest,但不要'当您想提供自定义实时日志记录格式时,不要试图这样做。其他读取 setup.cfg 的工具可能会将 %(message)s 之类的内容视为字符串插值并失败。无论如何,最好的选择是使用 pyproject.toml ,但如果您被迫使用旧的 ini 样式格式,请坚持使用 pytest.ini 以避免错误。

Since version 3.3, pytest supports live logging, meaning that all the log records emitted in tests will be printed to the terminal immediately. The feature is documented under Live Logs section. Live logging is disabled by default; to enable it, set log_cli = 1 in the pyproject.toml1 or pytest.ini2 config. Live logging supports emitting to terminal and file; the relevant options allow records customizing:

terminal:

  • log_cli_level
  • log_cli_format
  • log_cli_date_format

file:

  • log_file
  • log_file_level
  • log_file_format
  • log_file_date_format

As pointed out by Kévin Barré in this comment, overriding ini options from command line can be done via:

-o OVERRIDE_INI, --override-ini=OVERRIDE_INI
        override ini option with "option=value" style, e.g.
        -o xfail_strict=True -o cache_dir=cache

So instead of declaring log_cli in pytest.ini, you can simply call:

$ pytest -o log_cli=true ...

Examples

Simple test file used for demonstrating:

# test_spam.py

import logging

LOGGER = logging.getLogger(__name__)


def test_eggs():
    LOGGER.info('eggs info')
    LOGGER.warning('eggs warning')
    LOGGER.error('eggs error')
    LOGGER.critical('eggs critical')
    assert True

As you can see, no extra configuration needed; pytest will setup the logger automatically, based on options specified in pytest.ini or passed from command line.

Live logging to terminal, INFO level, fancy output

Configuration in pyproject.toml:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "INFO"
log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"

The identical configuration in legacy pytest.ini:

[pytest]
log_cli = 1
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_cli_date_format=%Y-%m-%d %H:%M:%S

Running the test:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
2018-08-01 14:33:20 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:33:20 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:33:20 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:33:20 [CRITICAL] eggs critical (test_spam.py:10)
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

Live logging to terminal and file, only message & CRITICAL level in terminal, fancy output in pytest.log file

Configuration in pyproject.toml:

[tool.pytest.ini_options]
log_cli = true
log_cli_level = "CRITICAL"
log_cli_format = "%(message)s"

log_file = "pytest.log"
log_file_level = "DEBUG"
log_file_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
log_file_date_format = "%Y-%m-%d %H:%M:%S"

The identical configuration in legacy pytest.ini:

[pytest]
log_cli = 1
log_cli_level = CRITICAL
log_cli_format = %(message)s

log_file = pytest.log
log_file_level = DEBUG
log_file_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_file_date_format=%Y-%m-%d %H:%M:%S

Test run:

$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item

test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
eggs critical
PASSED                                                                        [100%]

============================= 1 passed in 0.01 seconds =============================

$ cat pytest.log
2018-08-01 14:38:09 [    INFO] eggs info (test_spam.py:7)
2018-08-01 14:38:09 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:38:09 [   ERROR] eggs error (test_spam.py:9)
2018-08-01 14:38:09 [CRITICAL] eggs critical (test_spam.py:10)

1 pyproject.toml supported since version 6.0 and is the best option IMO. See PEP 518 for the specs.

2 Although you can also configure pytest in setup.cfg under the [tool:pytest] section, don't be tempted to do that when you want to provide custom live logging format. Other tools reading setup.cfg might treat stuff like %(message)s as string interpolation and fail. The best choice is using pyproject.toml anyway, but if you are forced to use the legacy ini-style format, stick to pytest.ini to avoid errors.

舞袖。长 2024-10-19 00:59:29

使用 pytest --log-cli-level=DEBUG 可以与 pytest 配合使用(从 6.2.2 到 7.1.1 进行测试)

使用 pytest --log-cli-level=DEBUG --capture =tee-sys 还将打印 stdtout

Using pytest --log-cli-level=DEBUG works fine with pytest (tested from 6.2.2 to 7.1.1)

Using pytest --log-cli-level=DEBUG --capture=tee-sys will also print stdtout.

掩饰不了的爱 2024-10-19 00:59:29

对我有用,这是我得到的输出: [snip ->示例不正确]

编辑:似乎您必须将 -s 选项传递给 py.test,这样它就不会捕获标准输出。在这里(未安装 py.test),使用 python pytest.py -s pyt.py 就足够了。

对于您的代码,您只需将 args 中的 -s 传递给 main

 pytest.main(args=['-s', os.path.abspath(__file__)])

请参阅 捕获输出

Works for me, here's the output I get: [snip -> example was incorrect]

Edit: It seems that you have to pass the -s option to py.test so it won't capture stdout. Here (py.test not installed), it was enough to use python pytest.py -s pyt.py.

For your code, all you need is to pass -s in args to main:

 pytest.main(args=['-s', os.path.abspath(__file__)])

See the py.test documentation on capturing output.

千笙结 2024-10-19 00:59:29

要打开记录器输出,请从命令行发送 --capture=no 标志。
--capture=no 将显示记录器和打印语句的所有输出。如果您想捕获记录器的输出而不是打印语句,请使用 --capture=sys

pytest --capture=no tests/system/test_backoffice.py

这里是有关“捕获 stdout/stderr 输出”的更多信息

默认记录器输出级别为“警告”
要更改日志输出级别,请使用 --log-cli-level 标志。

pytest --capture=no --log-cli-level=DEBUG tests/system/test_backoffice.py

To turn logger output on use send --capture=no flag from command line.
--capture=no will show all outputs from logger and print statements. If you would like to capture outputs from logger and not print statements use --capture=sys

pytest --capture=no tests/system/test_backoffice.py

Here is more information about "Capturing of the stdout/stderr output"

By default logger output level is "WARNING"
To change log output level use --log-cli-level flag.

pytest --capture=no --log-cli-level=DEBUG tests/system/test_backoffice.py
动听の歌 2024-10-19 00:59:29

如果你想用命令行过滤日志,可以通过 --log-cli-level (pytest --log-cli-level)
并且日志将从您指定的级别及以上显示

(例如 pytest --log-cli-level=INFO 将显示 INFO 及以上日志(警告、错误、严重))

请注意:默认 -如果您未指定 -log-cli-level ,则会出现警告(https: //docs.pytest.org/en/6.2.x/logging.html

但是如果你不想每次使用pytest时都使用--log-cli-level
您可以设置日志级别
在你的 pytest 配置文件(pytest.ini/tox.ini/setup.cfg)中,

例如

log-level=INFO 放入 pytest.ini (或我提到的其他配置文件)中

,当你运行 时, pytest,你只能看到INFO及以上日志

If you want to filter logs with the command line, you can pass --log-cli-level (pytest --log-cli-level)
and logs will be shown from the level you specified and above

(e.g. pytest --log-cli-level=INFO will show INFO and above logs(WARNING, ERROR, CRITICAL))

note that: default --log-cli-level is a WARNING if you don't specify it (https://docs.pytest.org/en/6.2.x/logging.html)

But if you dont want to use --log-cli-level every time use pytest,
you can set log-level
in your pytest config file (pytest.ini/tox.ini/setup.cfg)

e.g.

put log-level=INFO in pytest.ini (or other config files i mentioned)

when you run pytest, you only see INFO and above logs

佼人 2024-10-19 00:59:29

如果您使用 vscode,请使用以下配置,假设您已安装
适用于您的 Python 项目的 Python 官方插件 (ms-python.python)。

下的 ./.vscode/setting.json

{
  ....
  "python.testing.pytestArgs": ["-s", "src"], //here before discover-path src
  "python.testing.unittestEnabled": false,
  "python.testing.nosetestsEnabled": false,
  "python.testing.pytestEnabled": true,
  ...
}

您的项目 一些插件可以使用它,包括但不限于

  • 适用于 Visual Studio Code 的 Python 测试资源管理器 (littlefoxteam.vscode-python-test-adapter )
  • Visual Studio Code 测试资源管理器(hbenl.vscode-test-explorer)

If you use vscode, use following config, assuming you've installed
Python official plugin (ms-python.python) for your python project.

./.vscode/setting.json under your proj

{
  ....
  "python.testing.pytestArgs": ["-s", "src"], //here before discover-path src
  "python.testing.unittestEnabled": false,
  "python.testing.nosetestsEnabled": false,
  "python.testing.pytestEnabled": true,
  ...
}

P.S. Some plugins work on it, including but not limited to:

  • Python Test Explorer for Visual Studio Code (littlefoxteam.vscode-python-test-adapter)
  • Test Explorer for Visual Studio Code(hbenl.vscode-test-explorer)
花心好男孩 2024-10-19 00:59:29

您可以阅读:
pytest 日志记录
这是一个简单的示例,您可以运行 foo 函数并获取日志。

#./test_main.py
from main import foo
import logging

def test_foo(caplog):
    caplog.set_level(logging.INFO)

    logging.getLogger().info('Log inside a test function!')

    assert foo(1, 2) == 5
    /* your test here*/
# ./main.py
import logging

def foo(a, b):
    logging.getLogger().info('a: ' + str(a))
    logging.getLogger().info('b: ' + str(b))
    return a + b

现在您可以运行 pytest 并从您需要的函数中获取日志信息。
如果没有任何错误,日志将被省略。

You can read:
Documentation for logging in pytest
Here is simple example that you can run and get log from foo function.

#./test_main.py
from main import foo
import logging

def test_foo(caplog):
    caplog.set_level(logging.INFO)

    logging.getLogger().info('Log inside a test function!')

    assert foo(1, 2) == 5
    /* your test here*/
# ./main.py
import logging

def foo(a, b):
    logging.getLogger().info('a: ' + str(a))
    logging.getLogger().info('b: ' + str(b))
    return a + b

Now you can run pytest and get log info from function that you need.
If you don't have any errors, logs will be omitted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文