Python测试:如何确保下游函数调用上游的传参错误被测试捕获
解决方案
1. 优先使用关键字参数传参
从根源避免参数顺序错误问题,所有调用inner的位置都显式指定参数名:
# 正确写法,不受参数顺序调整影响 info = inner(age=age, name=name)
后续如果修改inner的参数顺序,只要参数名不变,调用逻辑不需要修改;如果修改了参数名,IDE、静态检查工具会直接标记错误,不需要等到测试阶段发现。
2. 引入静态类型检查
给函数加上类型注解,配合mypy等静态检查工具提前捕获类型不匹配的参数传递错误:
# functions.py 增加类型注解 def inner(age: int, name: str) -> str: if age > 18: return f'{name} is an adult.' else: return f'{name} is a child.' def outer(name: str, age: int) -> str: # 这里传参顺序错误的话,mypy会直接报错:Argument 1 to "inner" has incompatible type "str"; expected "int" info = inner(name, age) return f'This is {name}. {info}'
不需要跑测试,在编码阶段就能发现绝大多数参数顺序错误问题。
3. 优化mock校验逻辑,绑定原函数签名校验
不要手动写死assert_called_once_with的参数,而是自动获取原函数的签名,校验mock收到的参数是否符合签名要求,这样只要上游函数参数定义修改,下游测试不用改就能自动识别不匹配的调用:
import inspect from functions import inner def test_outer(): name, age = "John", 43 mock_get_info = Mock() mock_get_info.return_value = "Info" patch_get_info = patch("functions.inner", new=mock_get_info) with patch_get_info: info = outer(name, age) expected = 'This is John. Info' assert info == expected # 新增签名校验逻辑 call_args = mock_get_info.call_args inner_sig = inspect.signature(inner) # 这里如果参数不匹配会直接抛出TypeError,捕获参数顺序、数量、类型不匹配问题 inner_sig.bind(*call_args.args, **call_args.kwargs)
这种方式既保留了mock返回自定义值的能力,不需要处理inner的大返回值,又能自动对齐上游函数的参数定义,不会出现mock自洽的假阳性测试结果。
4. 补充轻量集成测试
新增不需要mockinner的集成测试用例,用小体量的测试数据验证调用链路的正确性,不需要覆盖大返回值场景,只要验证参数传递正确即可:
def test_outer_integration(): name, age = "John", 43 info = outer(name, age) # 只需要校验返回值包含预期的基础结构,不需要完整校验inner的大返回内容 assert 'This is John.' in info assert 'John is an adult.' in info
内容的提问来源于stack exchange,提问作者Hein Schnell
相关产品推荐
相关产品推荐

