我正在尝试使用Pytest对处理csv文件的函数进行单元测试。虽然我的函数可以正常工作,但在创建“样本”csv文件以测试函数时,感觉代码重复很多,实际包含真实数据的csv文件有数百万条记录。
这些不是我要在模块中测试的唯一csv文件,因此,了解处理不同文件结构的函数的最佳测试方法将非常有帮助。
目前,我正在创建一个非常简短的csv文件,以模仿实际文件模式及其单行数据,然后通过函数处理后预期生成数据框输出。
也许利用 mocking 是可行的?但是我认为你不应该需要为这种类型的测试进行 mocking。
测试函数
@pytest.mark.parametrize('test_file, expected', [
(r'Path\To\Project\Output\Folder\mock_sales1.csv',
pd.DataFrame([['A0A0A0', 1, 4000]], columns=['Postal_Code', 'Store_Num', 'Sales'])),
(r'Path\To\Project\Output\Folder\mock_sales2.csv',
pd.DataFrame([['A0A0A0', 1, 4000]], columns=['Postal_Code', 'Store_Num', 'Sales']))
])
def test_sales_dataframe(test_file, expected):
# This part is repetitive, different tests each need a seperate file written within the test function.
# Writing sample file to test that files with 7 columns are read correctly.
mock_mks_sales1 = [['Data0', 'A0A0A0', 1, 'Data3', 'Data4', 'Data5', 4000]]
with open(r'Path\To\Project\Output\Folder\mock_sales1.csv', 'w') as file:
writer = csv.writer(file)
writer.writerows(mock_sales1)
# Writing sample file to test that files with 8 columns are read correctly.
mock_mks_sales2 = [['Data0', 'A0A0A0', 1, 'Data3', 'Data4', 'Data5', 'Data6', 4000]]
with open(r'Path\To\Project\Output\Folder\mock_sales2.csv', 'w') as file:
writer = csv.writer(file)
writer.writerows(mock_sales2)
sales_df = mks_sales_dataframe(test_file)
testing.assert_frame_equal(expected, sales_df)
os.remove(r'Path\To\Project\Output\Folder\mock_sales1.csv')
os.remove(r'Path\To\Project\Output\Folder\mock_sales2.csv')
主函数
def sales_dataframe(file):
try:
with open(file, 'r') as f:
reader = csv.reader(f)
num_cols = len(next(reader))
columns = [1, 2, (num_cols - 1)] # Number of columns is variable, this is used later to accurately specify which columns should be read. This is part I'm testing!
sales_df = pd.read_csv(file, usecols=columns, names=['Postal_Code', 'Store_Num', 'Sales'])
return sales_df
except FileNotFoundError:
raise FileNotFoundError(file)
测试按预期通过。但是,每当我要进行不同的测试时,都必须在测试函数中创建一个样本csv文件,并在测试完成后删除每个文件。可以想象,这在单个测试函数中会产生大量重复的代码,感觉相当笨重和啰嗦,特别是当测试被参数化时。
test_sales_dataframe
中,您首先创建了mock_sales1.csv
和mock_sales2.csv
文件,并填充了固定内容,然后调用mks_sales_dataframe
读取其中一个 .csv 文件,最后检查结果是否等于expected
? - pschillmock_sales1.csv
和mock_sales2.csv
(以及所有其他测试数据文件)存储在与测试代码相邻的testdata
文件夹中。然后,你的测试就变成了两行代码:sales_df = mks_sales_dataframe(test_file)
和testing.assert_frame_equal(expected, sales_df)
。 - pschill