如何在pytest中同时直接和间接使用parametrize参数化?
解决pytest参数化中直接用参数与间接fixture匹配的问题
你遇到的问题本质是多层参数化生成了笛卡尔积——类上的number参数化和测试函数上的square_number间接参数化组合后,会生成所有可能的参数对,自然出现1-2、2-1这种不匹配的失败用例。
下面给两种直接解决的方案,都能实现你要的“参数一一对应,只跑匹配用例”的效果:
方案1:让fixture返回原参数+计算结果的组合
修改fixture,同时返回传入的原始数字和计算出的平方值,测试函数直接解构使用即可,不用额外参数化number:
import pytest def calculate_square(num: int): return num ** 2 args = [1, 2] class TestSomething: @pytest.fixture(scope='function') def number_with_square(self, request): raw_num = request.param # 返回原参数和计算后的平方值组成的元组 yield raw_num, calculate_square(raw_num) @pytest.mark.parametrize('number_with_square', args, indirect=True) def test_first_thing(self, number_with_square): number, square_number = number_with_square assert number ** 2 == square_number
执行后会得到你想要的结果:
q.py::TestSomething::test_first_thing[1] PASSED q.py::TestSomething::test_first_thing[2] PASSED
方案2:测试函数直接通过request获取参数化的原始值
如果不想修改fixture的返回值,也可以在测试函数里通过request.param直接拿到传给square_number的原始参数,这样不用额外定义number参数:
import pytest def calculate_square(num: int): return num ** 2 args = [1, 2] class TestSomething: @pytest.fixture(scope='function') def square_number(self, request): yield calculate_square(request.param) @pytest.mark.parametrize('square_number', args, indirect=True) def test_first_thing(self, square_number, request): # request.param就是当前传给square_number的原始参数 number = request.param assert number ** 2 == square_number
这个方案同样能得到预期的执行结果,而且不需要改动fixture的逻辑。
为什么原来的代码会出错?
因为你在类上做了number的参数化,又在测试函数上做了square_number的参数化,pytest会自动生成两组参数的所有组合(笛卡尔积),所以出现了4个测试用例,其中一半是不匹配的。解决的核心就是避免不必要的多层参数化,让参数一一对应。
内容的提问来源于stack exchange,提问作者David Gard
相关产品推荐
相关产品推荐

