如何将pytest fixture传递给非pytest代码以通过测试断言?
问题描述
正常调用f.result时返回值为1,但测试f时,希望将fixture my_var的返回值传递给f,使test_stuff中的assert断言结果为True。是否有pytest特性可实现此需求?
现有代码
conftest.py
import pytest @pytest.fixture() def my_var(): b = 2 return b
test_stuff.py
import pytest from mycode import f def test_stuff(): assert f.result == 2
测试失败信息:
./tests/test_stuff.py::test_stuff Failed: [undefined]assert 1 == 2
- where 1 = f.result
def test_stuff():assert f.result == 2E assert 1 == 2
E + where 1 = f.resulttests/test_stuff.py:5: AssertionError
mycode.py
class f: ## Pytest fixture to cast b as my_var here? def thing(a: int, b: int = None) -> int: ## Or maybe a way to cast b as my_var here? if not b: return a else: return b result = thing(1) if __name__ == "__main__": print(f.result)
解决方案
方法1:调整业务代码,支持动态注入
当前f.result是类加载阶段就固定的(调用thing(1)得到1),要让它能接收fixture的值,得把result改成可动态更新的属性。比如用类属性的@property:
修改mycode.py:
class f: _b = None @classmethod def thing(cls, a: int, b: int = None) -> int: # 传入b时更新内部存储的_b if b is not None: cls._b = b # 优先返回_b,否则返回a return cls._b if cls._b is not None else a # 把result改成类属性的property,每次访问都会重新计算 @classmethod @property def result(cls): return cls.thing(1)
然后修改测试用例,先注入my_var的值:
import pytest from mycode import f def test_stuff(my_var): # 调用thing传入my_var的值,更新内部存储 f.thing(1, my_var) assert f.result == 2
这样测试时,f.result会返回注入的2,断言通过。
方法2:用pytest的monkeypatch直接替换属性值
如果不想改动业务代码,直接用pytest自带的monkeypatch fixture,在测试时替换f.result的值:
修改test_stuff.py:
import pytest from mycode import f def test_stuff(my_var, monkeypatch): # 直接把f.result替换成my_var返回的2 monkeypatch.setattr(f, 'result', my_var) assert f.result == 2
这种方法不需要修改业务代码,适合快速完成测试需求。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

