在pytest测试中记录


90

我想在测试函数中放入一些日志记录语句,以检查一些状态变量。

我有以下代码片段:

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从测试方法向控制台发出日志记录?


3
您可能会看一下py.test的创建者发布的答案。他建议使用pytest插件,以提供高度的多功能性。
2013年

Answers:


30

为我工作,这是我得到的输出:[snip-> example was not正确]

编辑:看来您必须将-s选项传递给py.test,以便它不会捕获stdout。在这里(未安装py.test)就足够了 python pytest.py -s pyt.py

对于你的代码,你需要的是通过-sargsmain

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

请参阅py.test文档以获取输出


抱歉。我匆匆粘贴了代码。请从“ test_one”函数中删除“ assert 0 == 1”,以注意“问题”。仅当出现某些故障(我通过使用错误的断言强制执行)时,py.test才会显示日志记录信息。
superselector

没问题,我发现了如何在命令行上进行修复,寻找一种编程方式。
TryPyPy 2011年

1
您还可以将日志记录输出重定向到某个文件,而不是默认的隐式stderr。
hpk42 2011年

@superselector hpk42是py.test家伙,请听。IIUC,在您的代码中为logging.basicConfig(filename="somelog.txt", level=logging.DEBUG)
TryPyPy 2011年

115

从3.3版开始,pytest支持实时日志记录,这意味着测试中发出的所有日志记录都将立即打印到终端。该功能记录在“实时日志”部分下。默认情况下,实时日志记录处于禁用状态;要启用它,请log_cli = 1pytest.ini配置1中进行设置。实时日志支持向终端和文件发射;相关选项允许记录定制:

终奌站:

  • log_cli_level
  • log_cli_format
  • log_cli_date_format

文件:

  • log_file
  • log_file_level
  • log_file_format
  • log_file_date_format

注意log_cli标志不能从命令行传递,必须在中设置pytest.ini。所有其他选项都可以从命令行传递,也可以在配置文件中设置。正如KévinBarré此注释中指出的那样,可以通过命令行选项从命令行覆盖ini-o/--override选项。因此,您无需调用log_cliin pytest.ini,而只需声明:

$ 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级别,高级输出

配置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文件中显示奇特的输出

配置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尽管您可以pytest在部分中setup.cfg进行配置[tool:pytest],但是当您要提供自定义实时日志记录格式时,请不要尝试这样做。其他工具读取setup.cfg可能会将诸如%(message)s字符串插值之类的内容视为失败。使用pytest.ini以避免错误。


17
关于log_cli必须在pytest.ini中的注释,看来您可以使用-ooption从命令行覆盖值。pytest -o log_cli=true --log-cli-level=DEBUG为我工作。
凯文·巴雷

@KévinBarré的评论非常好,总的来说非常有用,谢谢!更新了答案。
霍夫林

使用日志记录时,这绝对是正确的答案。尽管我喜欢区分测试内部的日志和被测系统内部的日志,但应该分开考虑。
CMCDragonkai

不幸的pytest是,@ CMCDragonkai在此方面受到一定限制。但是,这应该可以对应用程序中的测试进行特殊的日志记录配置来实现;关闭记录器中的传播,并添加一个记录到指定文件的“测试处理程序”。这样,pytest仅记录来自测试的记录,而自定义处理程序将处理SuT日志。
霍夫林

1
@OfekAgmon如果要存储pytest输出,可以使用--result-log参数(尽管请注意,已弃用,这里是替代方法)。但是,您不能将pytest输出和实时日志记录输出存储在同一文件中。
骑马
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.