在pytest测试中记录日志
在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__\'
块的日志消息被传输到控制台。
有没有一种方法可以强制 pytest
从测试方法中发出日志到控制台?
这对我来说没问题,这里是我得到的输出: [省略 -> 示例不正确]
编辑: 看起来你必须向py.test传递-s
选项,这样它就不会捕获stdout。 在这里(尚无安装py.test),只需要使用python pytest.py -s pyt.py
。
针对你的代码,你只需要在args
中传递-s
给main
即可:
pytest.main(args=['-s', os.path.abspath(__file__)])
请参阅py.test文档上的捕捉输出。
自从版本3.3以来,pytest
支持实时日志记录,这意味着测试中发出的所有日志记录将立即打印到终端上。该功能在实时日志记录部分有文档记录。实时日志记录默认情况下处于禁用状态;要启用它,请在pyproject.toml
1 或 pytest.ini
2 配置中设置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.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 自版本6.0起支持pyproject.toml
,我认为这是最好的选择。有关规范,请参见PEP 518。
2 虽然你也可以在setup.cfg
的[tool:pytest]
部分配置pytest
,但在想要提供自定义实时记录格式时不要被引诱这样做。其他读取setup.cfg
的工具可能将类似%(message)s
的内容视为字符串插值而导致错误。使用pyproject.toml
是最好的选择,但如果你被迫使用旧的ini-style格式,请使用pytest.ini
以避免错误。