pytest每个测试方法实现一个日志文件

时间:2016-12-30 18:12:14

标签: pytest

我想为每个测试方法创建一个单独的日志文件。我想在conftest.py文件中执行此操作,并将日志文件实例传递给测试方法。这样,每当我在测试方法中记录某些东西时,它就会记录到一个单独的日志文件中,并且很容易分析。

我尝试了以下内容。 在conftest.py文件中我添加了这个:

logs_dir = pkg_resources.resource_filename("test_results", "logs")
def pytest_runtest_setup(item):
    test_method_name = item.name
    testpath = item.parent.name.strip('.py')
    path = '%s/%s' % (logs_dir, testpath)
    if not os.path.exists(path):
        os.makedirs(path)
    log = logger.make_logger(test_method_name, path) # Make logger takes care of creating the logfile and returns the python logging object.

这里的问题是pytest_runtest_setup无法向测试方法返回任何内容。至少,我不知道。

所以,我想在conftest.py文件中用scope =“function”创建一个fixture方法,并从测试方法中调用这个fixture。但是,fixture方法不知道Pytest.Item对象。在pytest_runtest_setup方法的情况下,它接收item参数并使用它我们能够找到测试方法名称和测试方法路径。

请帮忙!

3 个答案:

答案 0 :(得分:1)

在较新的pytest版本中,可以使用set_log_path实现。

@pytest.fixture
def manage_logs(request, autouse=True):
    """Set log file name same as test name"""

    request.config.pluginmanager.get_plugin("logging-plugin")\
        .set_log_path(os.path.join('log', request.node.name + '.log'))

答案 1 :(得分:0)

我找到了我正在寻找的答案。 我能够使用像这样的函数作用夹具来实现它:

@pytest.fixture(scope="function")
def log(request):
    test_path = request.node.parent.name.strip(".py")
    test_name = request.node.name
    node_id = request.node.nodeid
    log_file_path = '%s/%s' % (logs_dir, test_path)
    if not os.path.exists(log_file_path):
        os.makedirs(log_file_path)
    logger_obj = logger.make_logger(test_name, log_file_path, node_id)
    yield logger_obj
    handlers = logger_obj.handlers
    for handler in handlers:
        handler.close()
        logger_obj.removeHandler(handler)

答案 2 :(得分:0)

我通过进一步研究webh的答案找到了这种解决方案。我尝试使用pytest-logger,但是它们的文件结构非常严格,对我而言并没有太大用处。我发现this code无需任何插件即可工作。它基于set_log_path,这是一项实验性功能。

Pytest 6.1.1和Python 3.8.4

# conftest.py

# Required modules
import pytest
from pathlib import Path

# Configure logging
@pytest.hookimpl(hookwrapper=True,tryfirst=True)
def pytest_runtest_setup(item):
    config=item.config
    logging_plugin=config.pluginmanager.get_plugin("logging-plugin")
    filename=Path('pytest-logs', item._request.node.name+".log")
    logging_plugin.set_log_path(str(filename))
    yield

请注意,Path可以代替os.path.join的使用。此外,可以在不同的文件夹中设置不同的测试,并通过在文件名上使用时间戳来记录历史上进行的所有测试。例如,可以使用以下文件名:

# conftest.py

# Required modules
import pytest
import datetime
from pathlib import Path

# Configure logging
@pytest.hookimpl(hookwrapper=True,tryfirst=True)
def pytest_runtest_setup(item):
   ...
   filename=Path(
      'pytest-logs',
       item._request.node.name,
       f"{datetime.datetime.now().strftime('%Y%m%dT%H%M%S')}.log"
       )
   ...

此外,如果要修改日志格式,可以按照documentation中的说明在pytest配置文件中进行更改。

# pytest.ini
[pytest]
log_file_level = INFO
log_file_format = %(name)s [%(levelname)s]: %(message)

我的第一个堆栈溢出答案!