【问题标题】:pytest implementing a logfile per test methodpytest 为每个测试方法实现一个日志文件
【发布时间】:2016-12-30 18:12:14
【问题描述】:

我想为每个测试方法创建一个单独的日志文件。我想在 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 方法不知道 Pytest.Item 对象。对于 pytest_runtest_setup 方法,它接收 item 参数并使用它可以找出测试方法名称和测试方法路径。

请帮忙!

【问题讨论】:

    标签: pytest


    【解决方案1】:

    我通过进一步研究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"
           )
       ...
    

    另外,如果想修改日志格式,可以在pytest配置文件中进行更改,如documentation中所述。

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

    我的第一个 stackoverflow 答案!

    【讨论】:

      【解决方案2】:

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

      @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)
      

      【讨论】:

        【解决方案3】:

        在较新的 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'))
        

        【讨论】:

          猜你喜欢
          • 2021-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-07
          相关资源
          最近更新 更多