模拟方法中给出的路径 - Python

Mocking a path which is given in a method - Python

如何模拟路径 (".test/locations.yml),因为它不存在于我 运行 我的测试项目中。它存在于 CI环境。

我测试了我的功能 get_matches_mr 然后它说找不到路径位置文件

你有什么想法吗?

代码

def read_location_file():
    locations_file_path = os.path.join(".test/location.yml")

    if not os.path.isfile(locations_file_path):
        raise RuntimeError("Location file not found: " + locations_file_path)
    with open(locations_file_path, "r") as infile:
        location_file = yaml.safe_load(infile.read())
        test_locations= location_file["paths"]
    return test_locations



def get_matches_mr(self):

    merge_request = MergeRequest()
    locations = self.read_location_file()
    data_locations= merge_request.get_matches(locations)

    return data_locations

就像评论中建议的那样,我还要说测试这种情况的最佳方法是模拟 read_location_file。因为像 os.path.join 这样模拟文件系统方法意味着您将测试限制在某个实现上,这是一种不好的做法。单元测试套件不应该知道实现细节,而只知道要测试的接口。通常,在测试驱动开发中,您在实现逻辑之前编写测试。这样你甚至不知道 os.path.join 被使用了。

下面的代码展示了如何模拟 read_location_file 方法。假设包含您的两个方法的 class 称为 ClassToBeTested(替换为您的实际 class 名称)。

import os.path

from class_to_test import ClassToBeTested


def test_function_to_test(tmpdir, monkeypatch):
    def mockreturn():
        return [
            os.path.join(tmpdir, "sample/path/a"),
            os.path.join(tmpdir, "sample/path/b"),
            os.path.join(tmpdir, "sample/path/c"),
        ]

    monkeypatch.setattr(ClassToBeTested, 'read_location_file', mockreturn)

    c = ClassToBeTested()
    assert c.get_matches_mr()

注意:我使用固定装置 tmpdir and monkeypatch,它们都是 pytest 的内置插件:

  • 请参阅 以查找有关 tmpdir 的一些信息(在我解释的链接答案中 tmp_path,但它提供与 tmpdir 相同的概念;不同之处在于tmp_path returns 一个 pathlib.Path 对象,tmpdir returns 一个 py.path.local 对象)。
  • monkeypatch 是一个 pytest fixture,它为 mocking/patching 个对象提供方法。

将您的函数分成两部分:

  1. 正在查找并打开正确的文件。
  2. 正在读取和解析打开的文件。

你的函数只做第二部分;调用可以负责第一部分。

def read_location_file(infile):
    location_file = yaml.safe_load(infile.read())
    test_locations= location_file["paths"]
    return test_locations

然后您的测试代码可以使用 io.StringIO 之类的东西来验证您的函数是否可以正确解析它。

def test_read_location():
    assert read_location_file(io.StringIO("...")) == ...

您的生产代码将处理打开文件:

with open(location_file_path) as f:
    locations = read_location_file(f)