python - 在 pytest 测试中记录

标签 python logging pytest

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

我有以下代码片段:

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__' block 中的日志记录消息会传输到控制台。

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

最佳答案

从 3.3 版本开始,pytest 支持实时日志记录,这意味着测试中发出的所有日志记录都会立即打印到终端。该功能记录在 Live Logs 下。部分。默认情况下禁用实时日志记录;要启用它,请在 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é 所指出的那样在 this comment , 从命令行覆盖 ini 选项可以通过:

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

所以不用在 pytest.ini 中声明 log_cli,你可以简单地调用:

$ pytest -o log_cli=true ...

示例

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

# 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 以避免错误。

关于python - 在 pytest 测试中记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4673373/

相关文章:

pytest - 有没有办法跳过 pytest fixture ?

python - Python os.pathsep 的 Rust 等价物是什么?

python - 设置默认单元格大小

java - 在Springboot中创建2个日志文件

python - py.test 多次测试不同结果

python - 在 py.test 中多次调用同一个 fixture

python - 在 Python-Fu 中,将字符串包装在 N_() 中有何作用?

python - Python 中的 C 扩展 : Conver wchar string to Python Value

python - 使用信息级别记录不会产生任何输出

java - 能否在代码中的log4j.properties中设置指定的appender