You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python unittest测试仅打开特定文件名模式文件的函数

如何使用Python unittest测试仅打开特定文件名模式文件的函数

我来帮你搞定这个单元测试的问题!要验证你的get_tests()函数只处理符合test_*.json模式的文件,我们可以通过Mockglob.iglob和open这两个关键点来实现——完全不用依赖真实的文件系统,测试既可靠又快速。

核心思路

我们的测试要做两件事:

  1. 模拟glob.iglob返回混合的文件名列表(包含符合test_*.json的和不符合的)
  2. 追踪open函数的调用情况,最后断言只有符合模式的文件被实际打开了

这样就能精准验证函数的过滤逻辑是否符合预期,不会误打开其他文件。

完整测试代码示例

假设你的get_tests函数放在my_module.py里,测试代码可以这么写:

import unittest
from unittest import mock
from my_module import get_tests  # 导入要测试的函数

class TestGetTests(unittest.TestCase):
    def test_only_opens_test_json_files(self):
        # 1. 定义模拟的文件名列表:包含符合的和不符合的
        mock_file_paths = [
            "test_login.json",
            "subdir/test_checkout.json",
            "random.txt",
            "config.json",
            "test_data.xml"
        ]
        
        # 2. Mock glob.iglob,让它返回我们定义的文件名
        with mock.patch('glob.iglob', return_value=mock_file_paths):
            # 3. Mock open函数,同时模拟返回合法的JSON内容(避免json.loads报错)
            mock_file_content = '{"id": 1, "name": "test"}'
            with mock.patch('builtins.open', mock.mock_open(read_data=mock_file_content)) as mock_open:
                # 4. 调用要测试的函数
                result = get_tests()
                
                # 5. 断言:只有符合test_*.json的文件被打开
                expected_calls = [
                    mock.call("test_login.json"),
                    mock.call("subdir/test_checkout.json")
                ]
                mock_open.assert_has_calls(expected_calls, any_order=True)
                
                # 额外验证:返回的结果数量和符合条件的文件数量一致
                self.assertEqual(len(result), 2)

    def test_returns_empty_list_when_no_matching_files(self):
        # 模拟glob返回空列表或者全是不符合的文件
        with mock.patch('glob.iglob', return_value=["not_test.json", "readme.md"]):
            with mock.patch('builtins.open', mock.mock_open()):
                result = get_tests()
                
                # 断言open从未被调用
                mock.patch('builtins.open').assert_not_called()
                # 断言返回空列表
                self.assertEqual(result, [])

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

关键细节说明

  1. Mockglob.iglob的姿势
    我们直接让它返回预设的文件名列表,这样就能精准控制测试用的输入——不管真实文件系统里有什么,测试都只认我们给的这些文件名。

  2. Mockopen的注意点
    因为你的函数里用到了json.loads,所以必须让mock的open返回合法的JSON字符串,不然会抛出解析错误,打断测试流程。我们用mock.mock_open(read_data=...)来模拟文件内容。

  3. 验证调用的技巧

    • assert_has_calls用来检查open被调用的所有参数,any_order=True允许调用顺序和我们预设的不一致(因为glob.iglob的递归遍历顺序可能有变化,但这不影响结果)
    • assert_not_called用来验证当没有符合条件的文件时,open完全不会被触发
  4. 关于Patch的目标路径
    如果你要测试的函数在自己的模块里(比如my_module.py),要注意Mock的路径要和函数里实际引用的模块一致。比如函数里用的是glob.iglob,那我们就Patchglob.iglob;如果函数里是from glob import iglob,那就要Patchmy_module.iglob,这点别搞错!

备注:内容来源于stack exchange,提问作者RoyalSwish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 18:28:06