如何使用 pytest 将夹具中的对象共享到所有测试?
How to share object from fixture to all tests using pytest?
在具有会话范围和 autouse=True 的夹具中定义对象的最佳方法是什么,以便它可用于所有测试?
@pytest.fixture(scope='session', autouse=True)
def setup_func(request):
obj = SomeObj()
接下来,我想要一些之前创建的魔法 obj
将出现在每个测试上下文中,而不需要每个测试都定义 setup_func
夹具。
def test_one():
obj.do_something_fancy()
我的建议是将夹具添加到 conftest.py
并确保 return 您想要从夹具中生成的对象。
如前所述,这使得 "autouse" 有点没用。
在测试的根目录中,将夹具添加到名为 conftest.py
:
的文件中
@pytest.fixture(scope='session', autouse=True)
def someobj(request):
return SomeObj()
根文件下的任何测试文件都可以访问此夹具(例如 test_foo.py
):
def test_foo(someobj):
assert isinstance(someobj, SomeObj)
另一种方法是使用在同一测试中定义或从模块导入的全局变量。
例如 conftest.py
:
someobj = None
@pytest.fixture(scope='session', autouse=True)
def prep_someobj(request):
someobj = SomeObj()
那么在你的测试中:
from . import conftest
def test_foo():
assert isinstance(conftest.someobj, SomeObj)
在我看来,这比第一种方法可读性差,而且更麻烦。
另一种可能性是将测试包装在 class 中并使用 class 变量只定义一次对象实例。这假设您能够将所有测试包装在一个 class 中,因此这个答案可能会解决一个不太普遍但类似的用例。例如,
class SomeObj():
"""This object definition may exist in another module and be imported."""
def __init__(self):
self.x = 5
def do_something_fancy(self, y):
return self.x * y
class TestX():
# Object instance to share across tests
someobj = SomeObj()
def test_x(self):
assert TestX.someobj.x == 5
def test_fancy(self):
fancy_factor = 10
result = TestX.someobj.do_something_fancy(fancy_factor)
assert result == 50
一个更通用的模式是在您的会议结束时 return locals()
,您将能够轻松引用在夹具中创建的任何内容。
conftest.py
@pytest.fixture(scope='session')
def setup_func(request):
obj1 = SomeObj()
obj2 = SomeObj()
return locals()
test_stuff.py
def test_one(setup_func):
setup_func['obj1'].do_something_fancy()
def test_two(setup_func):
setup_func['obj2'].do_something_fancy()
在具有会话范围和 autouse=True 的夹具中定义对象的最佳方法是什么,以便它可用于所有测试?
@pytest.fixture(scope='session', autouse=True)
def setup_func(request):
obj = SomeObj()
接下来,我想要一些之前创建的魔法 obj
将出现在每个测试上下文中,而不需要每个测试都定义 setup_func
夹具。
def test_one():
obj.do_something_fancy()
我的建议是将夹具添加到 conftest.py
并确保 return 您想要从夹具中生成的对象。
如前所述,这使得 "autouse" 有点没用。
在测试的根目录中,将夹具添加到名为 conftest.py
:
@pytest.fixture(scope='session', autouse=True)
def someobj(request):
return SomeObj()
根文件下的任何测试文件都可以访问此夹具(例如 test_foo.py
):
def test_foo(someobj):
assert isinstance(someobj, SomeObj)
另一种方法是使用在同一测试中定义或从模块导入的全局变量。
例如 conftest.py
:
someobj = None
@pytest.fixture(scope='session', autouse=True)
def prep_someobj(request):
someobj = SomeObj()
那么在你的测试中:
from . import conftest
def test_foo():
assert isinstance(conftest.someobj, SomeObj)
在我看来,这比第一种方法可读性差,而且更麻烦。
另一种可能性是将测试包装在 class 中并使用 class 变量只定义一次对象实例。这假设您能够将所有测试包装在一个 class 中,因此这个答案可能会解决一个不太普遍但类似的用例。例如,
class SomeObj():
"""This object definition may exist in another module and be imported."""
def __init__(self):
self.x = 5
def do_something_fancy(self, y):
return self.x * y
class TestX():
# Object instance to share across tests
someobj = SomeObj()
def test_x(self):
assert TestX.someobj.x == 5
def test_fancy(self):
fancy_factor = 10
result = TestX.someobj.do_something_fancy(fancy_factor)
assert result == 50
一个更通用的模式是在您的会议结束时 return locals()
,您将能够轻松引用在夹具中创建的任何内容。
conftest.py
@pytest.fixture(scope='session')
def setup_func(request):
obj1 = SomeObj()
obj2 = SomeObj()
return locals()
test_stuff.py
def test_one(setup_func):
setup_func['obj1'].do_something_fancy()
def test_two(setup_func):
setup_func['obj2'].do_something_fancy()