【发布时间】:2021-10-05 15:44:02
【问题描述】:
我是 pytest 的新手,所以我可能会错误地使用一些 pytest 语义。
一般来说,我有以下问题:
我在测试中使用 mark.parametrize 进行模拟,当我在参数中使用相同的变量时,模拟使用的是上次运行的数据,而不是我指定的数据。
分析:
在第一次“迭代”中,在 mark.parametrize 中,我使用 mock_data_1 来模拟 GetData.get_data()。然后,我期望的测试在这里模拟data:data = GetData.get_data(),然后向数据data['new_col0'] 添加一个新列。
在第二次“迭代”中,我在 mark.parametrize 中再次使用 mock_data_1,而不是使用一组新的新 mock_data_1,测试使用以前的数据,包含额外的列。
这些是一些示例文件:
文件.py
from test_file_get_data import GetData
class MyClass:
def new_dataset(arg):
data = GetData.get_data(arg) # Mock this part
data[f'new_col{arg}'] = arg # New column to data
return data
test_file.py
from file import MyClass
import pandas as pd
import pytest
class TestMyClass:
mock_data_1 = pd.DataFrame({"col_1": [1,2,3]})
arg_1 = 0
arg_2 = 1
output_1 = pd.DataFrame({"col_1": [1,2,3], "new_col0": [0,0,0]})
output_2 = pd.DataFrame({"col_1": [1,2,3], "new_col1": [1,1,1]})
@pytest.mark.parametrize(
'mock_arguments, arg, result',
[
(mock_data_1, arg_1, output_1),
(mock_data_1, arg_2, output_2)
]
)
def test_new_dataset(self, mocker, mock_arguments, arg, result):
mocker.patch(
'file.GetData.get_data',
return_value=mock_arguments,
)
print(mock_arguments)
res = MyClass.new_dataset(arg)
print(res)
assert res.to_dict() == result.to_dict()
test_file_get_data.py
import pandas as pd
class GetData:
def get_data(arg):
data = pd.DataFrame({"a":[1, 2, 3]})
return data
所以第一个测试通过了,但是第二个测试失败了,因为返回的数据是这样的:
{'col_1': {1, 2, 3},
'new_col0': {0, 0, 0},
'new_col1': {1, 1, 1}}
而不是这个:
{'col_1': {1, 2, 3},
'new_col1': {1, 1, 1}}
如果我将data = GetData.get_data() 替换为data = GetData.get_data().copy(),则可以解决此问题,但我假设我在测试中做错了什么。
每次迭代后不应该刷新和/或删除数据吗? 或者正在发生的事情是预期的行为?
【问题讨论】:
-
你写的代码没有运行,请更正你的例子
-
除了代码无法按原样运行之外,您并没有展示
GetData的实际作用。我的猜测是它返回一个全局字典,每次调用都会对其进行操作,因此行为符合预期。 -
抱歉,我现在添加了一个可重现的示例。
标签: python pandas pytest pytest-mock