【问题标题】:Unittest - mock os.listdir is not used in testfunction / returns wrong valueUnittest - 模拟 os.listdir 未在 testfunction 中使用/返回错误值
【发布时间】:2022-01-14 13:51:51
【问题描述】:

我想测试以下函数,但仍然在努力寻找测试 I/O 操作的最佳实践。

def get_weight_file(path: Union[Path, str]) -> str:
    """Finds weights (.model) file in a directory

    Parameters
    ----------
    path: Union[Path, str]
        Path where to find the weights file

    Returns
    -------
    str
        Filename of the weights (.model) file

    """
    only_files = [
        file for file in os.listdir(path) if os.path.isfile(os.path.join(path, file))
    ]
    model_file = [file for file in only_files if file.endswith(".model")]

    if len(model_file) == 0:
        raise FileNotFoundError("No weights file found in current directory")
    if len(model_file) > 1:
        raise MultipleFilesError("Please provide a single weights file")

    return model_file[0]

我试图模拟 os.listdir。

@mock.patch("os.listdir", return_value=["test.model", "test.txt", "text.yaml"])
def test_get_weight_file(listdir):
    assert get_weight_file(path="./") == "test.model"

这是错误:

        if len(model_file) == 0:
>           raise FileNotFoundError("No weights file found in current directory")
E           FileNotFoundError: No weights file found in current directory

该函数似乎无法检索“test.model”文件。 无论如何,它不起作用,我不知道为什么,我也怀疑我解决这个问题的方法是最佳实践。谁能告诉我如何解决这个问题?

【问题讨论】:

  • 如果你的函数在模块foo中,而你的测试在不同的模块中,那么你需要修补foo.os.listdir

标签: python unit-testing python-unittest python-unittest.mock


【解决方案1】:

其实你应该给@mock.patch('os.listdir')打补丁,见where-to-patch

另外,我还修补了os.path.isfile()方法,因为我的真实文件系统上没有这些目录文件,所以我将它的返回值模拟为True

例如

get_weight_file.py:

import os


def get_weight_file(path):
    only_files = [
        file for file in os.listdir(path) if os.path.isfile(os.path.join(path, file))
    ]
    print('os.listdir(path): ', os.listdir(path))
    model_file = [file for file in only_files if file.endswith(".model")]
    return model_file[0]

test_get_weight_file.py:

from unittest import TestCase, mock
import unittest
from get_weight_file import get_weight_file


class TestGetWeightFile(TestCase):
    @mock.patch("os.path.isfile", return_value=True)
    @mock.patch("os.listdir", return_value=["test.model", "test.txt", "text.yaml"])
    def test_get_weight_file(self, mock_listdir, mock_isfile):
        print('mock_isfile: ', mock_isfile.return_value)
        print('mock_listdir: ', mock_listdir.return_value)
        assert get_weight_file(path="./") == "test.model"


if __name__ == '__main__':
    unittest.main()

测试结果:

mock_isfile:  True
mock_listdir:  ['test.model', 'test.txt', 'text.yaml']
os.listdir(path):  ['test.model', 'test.txt', 'text.yaml']
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2023-03-26
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多