【问题标题】:Why does logging with pytest parametrize return lines in logging, increment for every parameter?为什么使用 pytest 参数化日志记录中的返回行,为每个参数递增?
【发布时间】:2020-02-26 15:15:49
【问题描述】:

我编写了一个 Python 代码,我正在学习如何使用 pytest 和记录我正在做的测试。我想发送一个 pytest test_ 函数将循环遍历的参数列表。这是我的代码:

import pytest
import numpy as np
import logging

class TestClass:

    @pytest.fixture
    def initializeLogger(self):
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.DEBUG)

        formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')

        file_handler = logging.FileHandler(r'C:\Users\user\Data\Cross correlation\RunLog.log')
        file_handler.setFormatter(formatter)

        logger.addHandler(file_handler)
        return logger

    # Define parameters
    params = []
    params.append({'no' : 1})
    params.append({'no' : 2})
    params.append({'no' : 3})



    @pytest.mark.parametrize("params", params)
    def test_ZeroI(self, initializeLogger, params):
        logger = initializeLogger
        read = params['no']
        logger.info(f'Value inputted: {read}, Value read: {read}')
        print('success')
        assert params['no'] == read

我已经将 initializeLogger(self) 定义为一个 pytest 夹具,它在我的主要测试函数之前初始化:test_ZeroI(..) 被调用。

initializeLogger(self) 函数只是初始化记录器,我将它附加到为我创建文件的 file_handler。然后我返回记录器。

我创建了一个名为 params 的列表,并添加了键为“no”的字典值以及我想要遍历的值;所以在这种情况下:1、2、3。

testZeroI() 函数(根据我的理解)应该运行 3 次,参数 1、2 和 3 分别按顺序运行。我添加了以下行: logger.info(f'Value input: {read}, Value read: {read}') 它只是读取值并输出到日志中。

但是,问题出在日志中,这是我看到的:

INFO:module2:Value input: 1, Value read: 1 信息:模块2:输入的值:2,读取的值:2 信息:模块2:输入的值:2,读取的值:2 信息:模块2:输入的值:3,读取的值:3 信息:模块2:输入的值:3,读取的值:3 INFO:module2:Value input: 3, Value read: 3

如您所见,值 1 被记录一次。值 2 被记录两次。值 3 记录了 3 次。我在我的代码中做错了什么?我的目的是让我的代码输出这样的日志:

INFO:module2:Value input: 1, Value read: 1 信息:模块2:输入的值:2,读取的值:2 INFO:module2:Value input: 3, Value read: 3

【问题讨论】:

  • 在您的夹具initializeLogger 中,您每次都在同一个记录器上调用logger.addHandler(file_handler),因此您每次使用夹具时都会获得一个额外的记录器。您只需调用一次代码,例如通过检查它是否已初始化,或在类设置方法中。
  • 你知道是否有任何标记我可以使用它,以便在整个测试中只调用一次夹具函数 initializeLogger?
  • 我添加了一个不同可能性的答案。

标签: python logging pytest


【解决方案1】:

在您的夹具initializeLogger 中,您每次都在同一个记录器上调用logger.addHandler(file_handler),因此您每次使用夹具时都会获得一个额外的记录器。

您可以确保只调用一次代码(例如使用单例,或将其放入类设置中),或者在使用后删除记录器。
如果使用夹具,您可以这样做:

@pytest.fixture
def get_logger():
    logger = logging.getLogger(__name__)
    ...
    logger.addHandler(file_handler)
    yield logger
    logger.handlers.clear()

或者你也可以使用setup/teardown来做同样的事情:

class TestClass:

   def setup_method(self):
        self.logger = logging.getLogger(__name__)
        ...
        self.logger.addHandler(file_handler)

   def teardown_method(self):
       self.logger.handlers.clear()

如果您想在整个测试中使用相同的处理程序,您可以使用类初始化器:

class TestClass:
   logger = None

   @classmethod
   def setup_class(cls):
       cls.logger = initializeLogger()

   @classmethod
   def teardown_class(cls):
       cls.logger.handlers.clear()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2014-05-05
    • 1970-01-01
    • 2023-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多