本文介绍一种轻量、安全的模式:将耗时的初始化逻辑从 pytest 的参数收集阶段延迟到测试执行阶段,通过传递可调用对象(如函数或 partial 对象)并在测试体内调用,避免提前实例化,同时兼容不同签名的初始化函数。
在使用 @pytest.mark.parametrize 时,一个常见但易被忽视的问题是:所有参数表达式都会在 pytest 的测试收集(collection)阶段立即求值。这意味着像 fun1()、fun2() 或 [fun3(n) for n in range(10)] 这样的调用,会在你运行 pytest –collect-only 时就全部执行——即使你只打算运行其中某个子集,甚至只是查看测试列表。这对初始化开销大(如加载模型、连接数据库、生成大型数据结构)的函数而言,会显著拖慢收集速度、增加内存占用,还可能引发意外副作用(如网络请求失败导致收集中断)。
解决思路很清晰:不传“结果”,而传“如何得到结果”的可调用对象(即“thunk”),并在测试函数内部按需调用。这样,初始化严格发生在测试执行时(test_foobar 被调用的那一刻),完全规避收集期开销。