PyTest中如何将一个fixture设置的数据集作为另一个fixture的参数
结论
可以将fixture生成的全局数据作为另一个fixture的参数,你当前写法不生效的核心原因是fixture参数的执行时机不匹配。
问题根源
- fixture的
params参数是pytest在测试用例收集阶段就会解析的静态值,而json_datafixture是测试进入运行阶段后才会执行、从远端拉取数据的,收集阶段fixture还没运行,自然拿不到它的返回值 - 你现有代码里
params = json_data是把fixture函数对象本身传给了params,并不是函数的返回值,同时还存在语法错误:ids的列表推导式缺少右括号、scope参数缺少右引号
推荐实现方案
我们用pytest的pytest_generate_tests钩子实现动态参数化,既可以满足每个json条目作为独立测试用例执行的需求,也能实现全局只拉取一次远端数据的效果:
import pytest # 原有获取远端json数据的公共逻辑 def get_json_data(handle): # 你的原有拉取数据逻辑 pass def pytest_generate_tests(metafunc): # 仅对参数包含get_item的测试用例做参数化 if "get_item" in metafunc.fixturenames: # 此处根据你handle的实际来源调整获取方式,若handle是命令行参数可按下方写法获取 handle = metafunc.config.getoption("handle") # 全局仅拉取一次远端数据 json_data = get_json_data(handle) # 缓存数据供其他逻辑复用 metafunc.config.cache.set('json_data', json_data) # 动态完成参数化 metafunc.parametrize( "get_item", json_data, ids = [item['name'] for item in json_data], scope = "session" ) def test_global_data(get_item): # 每个json条目会作为独立用例执行,失败互不影响 assert get_item['value'] is not None
轻量替代方案
如果你的数据量很小,不需要每个条目作为独立用例,也可以直接在测试用例里嵌套调用fixture:
import pytest @pytest.fixture(scope='session') def json_data(request, handle): json_data = get_json_data(handle) request.config.cache.set('json_data', json_data) return json_data def test_global_data(json_data): for item in json_data: assert item['value'] is not None
注意该方案所有条目会合并为一个测试用例,单条数据校验失败会终止整个用例的执行。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

