繁体   English   中英

使用Pytest测试文件是否有效

[英]Using Pytest to test if a file is valid

我是 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() function。 这个 function 将 s3 上的文件路径、本地路径、s3 上的文件名和 append etag 值作为名称。 在任何给定时间,我们都可以检查路径/文件是否存在。 如果 etag 已更改,则该文件也将不存在,因为我们构造的 local_file_name 将无效。

测试方法

假设目前我有一个路径 foo/myfoo/etag_123_my_file.csv/

现在假设我将 go 更改为 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 功能本身,因此您主要需要检查它是否被正确调用,尽管您必须自己决定要测试什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM