Reputation: 351
I have a below code in my conftest.py
import pytest
@pytest.fixture(scope="class")
def fix1():
print("i am in fix1")
a = 10
return a
@pytest.fixture(scope="class")
def fix2():
print("i am in fix2")
b = 20
return b
@pytest.fixture(scope="session",autouse=True)
def setup_session(request):
tp = TestSetup(fix1)
tp.setup()
def teardown_session():
tp.teardown()
request.addfinalizer(teardown_session)
class TestSetup(object):
def __init__(self, fix1, fix2):
self.fix1 = fix1
self.fix2 = fix2
def setup(self):
print("i am in setup")
print(self.fix1)
def teardown(self):
print("I am in teardown")
print(self.fix2)
# py.test -s test1.py
=========== test session starts ===========
platform linux2 -- Python 2.7.5, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
rootdir: /tmp/test, inifile:
collected 2 items
test1.py i am in setup
<function fix1 at 0x2948320>
i am in test1
.i am in test2
.I am in teardown
when i execute the above using pytest, the fixtures fix1 and fix2 are never called. I need a way to call fix1 and fix2 as part of of setup and teardown before any of my tests runs.
What i am a trying to achieve is before any of my test runs, i need to have a setup created, the fix1, and fix2 are fixture which setup few things . I would like to have these fixture be called before any of my test runs and once all the tests are run , i call teardown function to teardown my setup.
Upvotes: 1
Views: 3954
Reputation: 7742
If what you want it to create a set of fixtures that get created once per session, reused for every test and then torn down, the py.test way of doing that would be:
import pytest
@pytest.fixture(scope="session")
def fix1(request):
# setup code here
print('creating fix1')
a = 10
def teardown_fix1():
# teardown code here
print('destroying fix1')
a = None
request.addfinalizer(teardown_fix1)
return a
def testOne(fix1):
print('in testOne')
assert fix1 == 10
def testTwo(fix1):
print('in testTwo')
assert fix1 != 20
(You already know how to do this, as shown in your code, so nothing new here).
You could have several of these session scoped fixtures, and the fact that they are session scoped guarantees that they will be created once, and then torn down at the end of the test run.
There is no need to have one master setup function that will set up every fixture and another which will tear them down, rather the idea is that you separate these into their own little factory functions with a finalizer as shown.
EDIT
But maybe there are a lot of fixtures that look pretty much the same, and you want to reuse some code. In that case, you could have a class that manages the fixtures and make that a pytest fixture. Then you declare other pytest fixtures that depend on the manager, each returning a specific fixture:
import pytest
class FixtureManager:
def __init__(self):
self.fixtures = {}
def setup(self):
print('setup')
self.fixtures['fix1'] = self.createFixture('fix1')
self.fixtures['fix2'] = self.createFixture('fix2')
self.fixtures['fix3'] = self.createFixture('fix3')
def get(self, name):
return self.fixtures[name]
def teardown(self):
print('teardown')
for name in self.fixtures.keys():
# whatever you need to do to delete it
del self.fixtures[name]
def createFixture(self, name):
# whatever code you do to create it
return 'Fixture with name %s' % name
@pytest.fixture(scope="session")
def fixman(request):
fixman = FixtureManager()
fixman.setup()
request.addfinalizer(fixman.teardown)
return fixman
@pytest.fixture
def fix1(fixman):
return fixman.get('fix1')
@pytest.fixture
def fix2(fixman):
return fixman.get('fix2')
def testOne(fix1):
print('in testOne')
assert fix1 == 'Fixture with name fix1'
def testTwo(fix2):
print('in testTwo')
assert fix2 == 'Fixture with name fix2'
Of course, you could do away with creating the fix1
, fix2
pytest fixtures, and get at those instead by injecting fixman
into your test functions and calling get
there. You be the judge what makes more sense and generates least boilerplate.
Upvotes: 0