如何避免pytest中pytest_generate_tests钩子被重复调用的问题
pytest重复生成测试数据优化方案
方案1:增加测试数据缓存(改造成本最低,不改变原有执行逻辑)
pytest的pytest_generate_tests钩子会在收集每个测试函数时触发,多个子类继承相同测试方法时会重复调用数据生成逻辑,新增全局缓存存储已生成的测试数据即可避免重复开销。
修改后的conftest.py代码示例:
import pytest import logging # 全局缓存:存储已生成的测试数据 _test_data_cache = {} @pytest.fixture(scope="class") def generic_test_setup(request, env): # 原有初始化逻辑保留 pass def pytest_generate_tests(metafunc): class_name = metafunc.cls.__name__.split('_')[1] # 优先从缓存读取数据,不存在再生成 if class_name not in _test_data_cache: logging.info(f"Collection Phase :: Initializing test_data for {class_name} !!!") # 原有生成test_data的逻辑不变 test_data = [] # 替换为你实际的测试数据生成代码 _test_data_cache[class_name] = test_data else: test_data = _test_data_cache[class_name] id_entity = [d['entity'] for d in test_data] if "data" in metafunc.fixturenames: # 新增scope="class",同一测试类下的所有方法复用同一参数实例 metafunc.parametrize("data", test_data, ids=id_entity, scope="class") @pytest.fixture def data(request): return request.param
如果Test_window和Test_door的测试数据完全一致,还可以进一步优化缓存逻辑,不按类名区分,直接复用同一份数据,完全避免二次生成。
方案2:参数化逻辑迁移到高优先级fixture
如果测试数据生成逻辑复杂度高,也可以将生成逻辑迁移到高scope的fixture中,利用fixture的生命周期实现跨用例复用:
import pytest import logging @pytest.fixture(scope="session") def test_data_pool(): return {} @pytest.fixture(scope="class") def generic_test_setup(request, env): # 原有初始化逻辑保留 pass @pytest.fixture(scope="class") def data(request, test_data_pool): class_name = request.cls.__name__.split('_')[1] if class_name not in test_data_pool: logging.info(f"Initializing test_data for {class_name} !!!") test_data = [] # 替换为你实际的测试数据生成代码 test_data_pool[class_name] = test_data return test_data_pool[class_name]
注意该方案需要配合@pytest.mark.parametrize(indirect=True)使用才能保留单条数据对应单条测试用例的特性,否则所有数据会作为一个整体传入测试方法,需要自行拆分用例。
内容的提问来源于stack exchange,提问作者surabhi
相关产品推荐
相关产品推荐

