python - 使用 Pytest 测试文件是否有效
问题描述
我是python的新手,对测试知之甚少。
背景
我是用python编写代码的新手,对测试知之甚少。因此,作为第一步,我浏览了PyTest文档以了解如何编写测试。我对固定装置是什么以及如何使用猴子补丁等有一个基本的了解。但是我有点难过,因为我不确定如何测试我的代码,因为网站上给出的示例不太实用。
我的代码
class Cache:
def __init__(self):
pass
def get_object_etag(self, s3_path: str, file_name: str) -> str:
bucket, key = s3.deconstruct_s3_path(f"{s3_path}/{file_name}")
return s3_resource().Object(bucket, key).e_tag
def file_exists(self, local_path: str, file_name: str) -> bool:
return os.path.exists(f"{local_path}/{file_name}")
def cache_file(self, s3_path: str, local_path: str, file_name_on_s3: str) -> None:
etag_value = self.get_object_etag(s3_path, file_name_on_s3)
local_file_name = "etag_" + etag_value + "_" + file_name_on_s3
if not self.file_exists(local_path, local_file_name):
os.makedirs(local_path, exist_ok=True)
s3.copy_with_python_retry(
from_path=f"{s3_path}/{file_name_on_s3}",
to_path=f"{local_path}/{local_file_name}",
)
else:
print("Cached File is Valid")
我想测试cache_file()函数。此函数将获取 s3 上的文件路径、本地路径、s3 上的文件名,并将 etag 值作为名称附加。在任何给定时间,我们都可以检查路径/文件是否存在。如果 etag 已更改,则该文件也将不存在,因为我们构造的 local_file_name 将无效。
测试方法
假设目前我有一个路径 foo/myfoo/etag_123_my_file.csv/
现在假设我转到 s3 并且由于某种原因 etag 已更改,因此我的文件名变为etag_124_my_file.csv
所以在这种情况下,我将无法通过文件存在检查并被迫再次下载更新的文件。
另一个测试用例是 s3 上的文件名与本地文件名匹配的理想情况,这意味着缓存文件是有效的。
我对如何测试这个感到非常困惑,因为我是测试 pytest 的新手并且没有测试驱动的心态。
例如,我是否使用猴子补丁并只设置诸如 local_file_name 和 e_tag_value 之类的属性?如果有人可以提供一个例子,我会很高兴。这对我开始测试世界有很大帮助。
解决方案
如果您模拟所有 S3 调用(有或没有某些框架),您可以例如模拟file_exists
返回False
,并检查是否s3.copy_with_python_retry
被调用,并在另一个测试中检查相反的情况(如果file_exists
返回则不调用True
)。
这是一个粗略的示例(不使用任何框架)来说明我的意思:
from unittest import mock
import pytest
from s3cache import Cache # assuming Cache is in s3cache.py
@pytest.fixture
def s3_mock():
with mock.patch('s3cache.s3') as s3_mock: # assuming you use "from boto3 import s3"
yield s3_mock
@pytest.fixture(autouse=True)
def get_object_mock():
# this is just for convenience - you mock the function as you don't test it
# autouse=True means it is mocked in all tests
with mock.patch('s3cache.Cache.get_object_etag') as object_mock:
yield object_mock
@mock.patch('os.makedirs')
@mock.patch('s3cache.Cache.file_exists', return_value=False)
def test_s3cache_exists(exists_mock, makedirs_mock, s3_mock):
cache = Cache()
# you can put more sensible value here
cache.cache_file("my_path", "local_path", "s3_fname")
makedirs_mock.assert_called_once_with('local_path', exist_ok=True)
# you can also check the arguments as above if needed
s3_mock.copy_with_python_retry.assert_called_once()
@mock.patch('os.makedirs')
@mock.patch('s3cache.Cache.file_exists', return_value=True)
def test_s3cache_not_existing(exists_mock, makedirs_mock, s3_mock):
cache = Cache()
cache.cache_file("my_path", "local_path", "s3_fname")
makedirs_mock.assert_not_called()
s3_mock.copy_with_python_retry.assert_not_called()
由于您不想测试 S3 功能本身,因此您主要需要检查它是否被正确调用,尽管您必须自己决定要测试什么。
推荐阅读
- reactjs - 如何自定义 MaterialUI 颜色阴影
- c++ - 进程以状态 -1073741510 终止 - C++ 素数分解
- oracle - 为什么我会收到 ORA-06531:对未初始化集合的引用?
- microsoft-graph-api - 如何从 Microsoft 图形 API 下载文件 (InputStream)?
- vb.net - 是否可以有一个文件来控制我可以从任何形式访问的自定义标题栏的外观和感觉?
- pandas - 聚合后如何将熊猫数据框转换为单个索引?
- javascript - 如何修改survey-react npm 库以更改默认颜色?
- python - 接受多个单词作为参数的 Discord 机器人
- python - 定义一个等于其他两个数组长度的新变量
- reactjs - 我正在尝试创建 React App 但我得到了这个输出?