I have a conftest.py:
import pytest
import asyncio
from some_library import MyLibrary
@pytest.fixture()
def event_loop(request):
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
@pytest.fixture(name="library_instance", scope='session')
def fixture_library_instance():
library = MyLibrary()
print("\nSetup Library")
library.config()
yield library
print("\nTeardown Library")
library = None
And a test file (test_1.py):
import pytest
class Test_Somemore:
@classmethod
def setup_class(self):
print("\nSetup Class")
@classmethod
def teardown_class(self):
print("\nTeardown Class")
@classmethod
def setup_method(self, method):
print("\nSetup Test = ", method.__name__)
@classmethod
def teardown_method(self, method):
print("\nTeardown Test = ", method.__name__)
@pytest.mark.usefixtures("library_instance")
@pytest.mark.asyncio
async def test_something_4(self, library_instance):
print(f"\ntest 4 - {library_instance.var}")
assert 1 == 1
assert library_instance.var == 100
@pytest.mark.usefixtures("library_instance")
@pytest.mark.asyncio
async def test_something_5(self, library_instance):
print(f"\ntest 5 - {library_instance.var}")
assert 2 == 2
assert library_instance.var == 100
@pytest.mark.usefixtures("library_instance")
@pytest.mark.asyncio
async def test_something_6(self, library_instance):
print(f"\ntest 6 - {library_instance.var}")
assert 3 == 3
assert library_instance.var == 100
The order it is being called is:
This is ok.
What I need is the following:
Basically something like this:
@classmethod
def setup_class(self):
print("\nSetup Class")
library_instance.foo1()
@classmethod
def teardown_class(self):
print("\nTeardown Class")
library_instance.foo2()
@classmethod
def setup_method(self, method):
print("\nSetup Test = ", method.__name__)
library_instance.foo3()
@classmethod
def teardown_method(self, method):
print("\nTeardown Test = ", method.__name__)
if test == FAIL:
library_instance.foo4()
Can somebody please help me?
Both your requirements are possible.
The first one (accessing another fixture in a setup method) is trivial if you change your setup/teardown methods to fixtures. In this case, you can just reference other fixtures of the same or a wider scope:
class TestSomemore:
@classmethod
@pytest.fixture(scope="class", autouse=True)
def prepare_class(cls, library_instance):
print("\nSetup Class")
library_instance.foo1()
yield
print("\nTeardown Class")
@pytest.fixture(autouse=True)
def prepare_method(self, request, library_instance):
print("\nSetup Test = ", request.node.name)
library_instance.foo2()
yield
print("\nTeardown Test = ", request.node.name)
A few remarks:
setup_class
and setup_method
but changed them for illustration. As soon as you make them fixtures, the name does not matter.autouse=True
(quite obvious, but I wanted to mention it).method
argument as in setup_method
won't work (it will be seen as a fixture name), but you can get the name via the request
fixture instead.Using the fixture notation arguably is preferrable to separate setup/teardown methods, as it only needs one method, and also allows the use of the same local variables for both setup and teardown (e.g. before and after the yield
), though that is also a matter of taste.
As for the second part (checking if a fixture has failed) - this has been nicely answered here, with a link to the relevant documentation, so I won't repeat it here.