pytest如何将测试类实例变量用作fixture参数实现数据可变的可复用测试
错误根因
报错是由@pytest.fixture的解析时机导致的:装饰器会在类定义加载阶段就执行,此时还没有生成类实例,self对象不存在,因此引用self.__testData会直接抛出NameError。pytest的fixture机制是在测试收集阶段完成解析的,确实不支持直接绑定类实例的属性作为参数。
实现方案1:继承基类+参数化标记(推荐)
把通用测试逻辑封装成测试基类,测试数据作为类属性由子类自定义,配合@pytest.mark.parametrize实现参数化,这是pytest生态下最符合规范的写法。
define_test.py 代码
#!/usr/bin/env python3 import pytest class TestDemoBase: # 子类继承后覆盖该属性传入测试数据 test_data = [] @pytest.fixture(scope='module', params=test_data) def fixture(self, request): return request.param def test(self, fixture): foo = fixture assert foo is not None
use_test.py 代码
#!/usr/bin/env python3 from define_test import TestDemoBase # 第一组测试用例 class TestDemo1(TestDemoBase): test_data = [1, 2, 3, 4] # 第二组测试用例 class TestDemo2(TestDemoBase): test_data = [4, 3, 2, 1]
直接执行pytest use_test.py -v即可,pytest会自动识别两个子类的测试用例,分别用对应的数据执行测试。
实现方案2:动态生成测试(适合运行时动态生成数据的场景)
如果你的测试数据需要在运行时动态计算、无法提前写死在类属性里,可以用pytest的pytest_generate_tests钩子动态注入参数。
define_test.py 代码
#!/usr/bin/env python3 def test_demo(fixture): foo = fixture assert foo is not None
use_test.py 代码
#!/usr/bin/env python3 from define_test import test_demo # 可以是任意运行时生成的动态数据 data1 = [1,2,3,4] data2 = [4,3,2,1] def pytest_generate_tests(metafunc): if "fixture" in metafunc.fixturenames: # 可根据测试函数名匹配注入不同的测试数据 if metafunc.function is test_demo: metafunc.parametrize("fixture", data1 + data2)
如果需要区分多组测试,也可以把测试逻辑封装成多个函数,分别对应不同的数据集即可。
内容的提问来源于stack exchange,提问作者twil
相关产品推荐
相关产品推荐

