python - 为什么使用 pytest 参数化日志记录中的返回行,为每个参数递增?
问题描述
我写了一个 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 INFO:module2:Value input: 2, Value read: 2 INFO:module2:Value input: 2, Value read: 2 INFO:module2:Value input: 3, Value read : 3 INFO:module2:Value input: 3, Value read: 3 INFO:module2:Value input: 3, Value read: 3
如您所见,值 1 被记录一次。值 2 被记录两次。值 3 记录了 3 次。我在我的代码中做错了什么?我的目的是让我的代码输出这样的日志:
INFO:module2:Value input: 1, Value read: 1 INFO:module2:Value input: 2, Value read: 2 INFO:module2:Value input: 3, Value read: 3
解决方案
在您的夹具中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()
推荐阅读
- testing - 在不同的端口上启动 Apollo Server 测试客户端
- python - 如何在没有字符串文字的情况下使用 Django 的包含?
- javascript - 如何在上传之前获取 html 文件输入的视频分辨率?
- python - Numpy 将较小的矩阵添加到较大的矩阵
- ios - ionic Cordova 苹果平台导出 .IPA 文件大小巨大
- android - 从同一个 Android 项目中获取两个签名的 APK
- javascript - 调用函数时不能清空Javascript数组
- couchdb - 使用设计文档将元素添加到列表中
- c - C中GtkImage的初始化
- angular - 如何根据 AG Grid Angular 中的值设置背景颜色列