如何让参数化Fixture的指定实例仅作用于特定测试模块?
解决方案
不需要将Fixture复制到每个测试模块,以下几种方法可以实现让参数化Fixture的指定实例仅作用于对应测试模块:
方法一:使用模块标记+Fixture跳过逻辑
这种方法通过给测试模块添加标记,让Fixture根据标记判断是否执行当前参数实例,既保留了Session级Fixture的复用性,又能精准控制每个模块的执行范围。
步骤1:修改conftest.py中的Fixture
去掉autouse=True,添加标记检查与跳过逻辑:
import pytest from nornir import InitNornir from nornir.core.filter import F @pytest.fixture(params=["rr", "cr", "bdr", "pe"], scope="session") def pytestnr(request): # 获取当前测试模块的device_type标记 device_type_mark = request.node.get_closest_marker("device_type") if device_type_mark and request.param != device_type_mark.args[0]: pytest.skip(f"当前模块仅测试{device_type_mark.args[0]}类型设备,跳过{request.param}实例") # 初始化Nornir nr = InitNornir( inventory={ "plugin": "NetBoxInventory2", "options": { "nb_url": my_secrets["netbox_url"], "nb_token": my_secrets["netbox_token"], "ssl_verify": False, "use_platform_napalm_driver": True, }, }, logging={"enabled": False}, ) nr = nr.filter(F(name__contains=request.param)) yield nr # 添加清理逻辑,释放资源 nr.close()
步骤2:给测试模块添加标记
比如在test_rr.py中添加模块级标记:
import pytest # 标记当前模块仅处理rr类型设备 pytestmark = pytest.mark.device_type("rr") def test_rr_config_check(pytestnr): # 编写你的测试逻辑 assert len(pytestnr.inventory.hosts) > 0
同理,test_cr.py中标记pytest.mark.device_type("cr")即可。运行时,每个模块只会执行对应参数的Fixture实例,其他实例会被自动跳过。
方法二:通过模块名称自动匹配参数
如果你的测试模块命名规范(比如test_rr.py、test_cr.py),可以直接通过模块名称提取目标设备类型,无需手动添加标记:
修改conftest.py中的Fixture:
import pytest from nornir import InitNornir from nornir.core.filter import F @pytest.fixture(params=["rr", "cr", "bdr", "pe"], scope="session") def pytestnr(request): # 从模块名称提取目标设备类型(假设模块名为test_xxx.py) module_name = request.node.module.__name__ target_type = module_name.split("_")[-1] if request.param != target_type: pytest.skip(f"当前模块{module_name}仅测试{target_type}类型设备,跳过{request.param}实例") # 初始化Nornir逻辑同方法一 nr = InitNornir( inventory={ "plugin": "NetBoxInventory2", "options": { "nb_url": my_secrets["netbox_url"], "nb_token": my_secrets["netbox_token"], "ssl_verify": False, "use_platform_napalm_driver": True, }, }, logging={"enabled": False}, ) nr = nr.filter(F(name__contains=request.param)) yield nr nr.close()
这种方法无需修改测试模块,依赖命名规则即可自动匹配,适合模块命名统一的场景。
方法三:抽取公共初始化逻辑,模块内定义专属Fixture
如果希望完全避免参数化Fixture的多实例问题,可以将初始化逻辑抽成公共函数,在每个测试模块中定义仅对应自身设备类型的Fixture:
步骤1:在conftest.py中定义公共初始化函数
from nornir import InitNornir from nornir.core.filter import F def init_nornir(device_type): nr = InitNornir( inventory={ "plugin": "NetBoxInventory2", "options": { "nb_url": my_secrets["netbox_url"], "nb_token": my_secrets["netbox_token"], "ssl_verify": False, "use_platform_napalm_driver": True, }, }, logging={"enabled": False}, ) return nr.filter(F(name__contains=device_type))
步骤2:在测试模块中定义专属Fixture
比如test_rr.py:
import pytest from conftest import init_nornir @pytest.fixture(scope="session") def pytestnr(): nr = init_nornir("rr") yield nr nr.close() def test_rr_connection(pytestnr): # 测试逻辑 pass
这种方法的优点是每个模块的Fixture仅生成对应实例,无多余跳过逻辑;缺点是每个测试模块都需要编写少量Fixture代码,但公共逻辑已抽取,重复度极低。
内容的提问来源于stack exchange,提问作者Suhaib Saeed
相关产品推荐
相关产品推荐

