如何从另一个fixture生成的列表参数化pytest fixture?
解决方案
有两种可行方案,根据你的列表生成逻辑是否依赖其他fixture来选择:
方案一:直接调用生成函数作为fixture参数(无依赖场景)
如果生成列表的函数不需要依赖其他fixture,直接在@pytest.fixture(params=)中调用该函数即可——params接受任意可迭代对象,函数返回的列表完全符合要求:
# conftest.py def create_a_list(): # 这里可以写任意生成逻辑,比如读取文件、计算生成 return [0, 1, 2, 3] # 直接调用生成函数获取参数化列表 @pytest.fixture(params=create_a_list()) def simple_fixture(request): return request.param
如果生成列表的操作耗时,希望仅执行一次,可以用缓存机制优化:
from functools import lru_cache @lru_cache(maxsize=None) def create_a_list(): print("仅执行一次的列表生成操作") return [0, 1, 2, 3] @pytest.fixture(params=create_a_list()) def simple_fixture(request): return request.param
测试代码保持不变(注意修正原代码的断言错误,应断言simple_fixture与result相等):
# test_my_script.py import pytest @pytest.mark.parametrize("result", [0,1,2,3]) def just_a_test(simple_fixture, result): assert simple_fixture == result
方案二:用pytest_generate_tests动态参数化(依赖其他fixture场景)
如果列表生成逻辑必须依赖其他fixture(比如需要数据库连接、配置项等),可以使用pytest的pytest_generate_tests钩子函数,在测试收集阶段动态为测试函数参数化:
# conftest.py import pytest def create_a_list(): return [0, 1, 2, 3] @pytest.fixture(scope="session") def generate_a(): # 这里可以依赖其他fixture,比如: # def generate_a(other_fixture): # return create_a_list(other_fixture) return create_a_list() def pytest_generate_tests(metafunc): # 检查当前测试函数是否需要simple_fixture参数 if "simple_fixture" in metafunc.fixturenames: # 获取generate_a fixture的结果 generated_list = metafunc.config.getfixturevalue("generate_a") # 为simple_fixture参数添加参数化 metafunc.parametrize("simple_fixture", generated_list)
测试代码无需修改(同样修正断言逻辑):
# test_my_script.py import pytest @pytest.mark.parametrize("result", [0,1,2,3]) def just_a_test(simple_fixture, result): assert simple_fixture == result
为什么你之前的尝试失败?
@pytest.fixture(params=)是在pytest收集测试用例阶段就需要确定参数列表的,而fixture的执行是在测试运行阶段,因此无法用一个fixture的结果来参数化另一个fixture的params。你代码中的yield from用法错误,fixture的yield是用于资源管理,并非用来动态生成参数化项的。
内容的提问来源于stack exchange,提问作者Ariba Siddiqi
相关产品推荐
相关产品推荐

