Reputation: 622
In my functional tests I need to create an object (which relates to a virtual server - not mocked one) which will be shared by a set of tests. Server is created with some py.test fixtures used (environment, host etc) to specify on which environment it's supposed to be set up - tests run on multiple different environments. My current approach is ugly, like this abstract example:
# [host, env, dns are fixtures, defined in conftest.py and passed from
# commandline args - py.test recognizes them so they can be changed
# each time the test is invoked from CLI]
@pytest.mark.parametrize(parameters_from_parametrize)
def test_something(host, env, dns):
server = Server(host,env, dns, random_name, random_passwd)
server.create()
server.do_stuff(parameters_from_parametrize)
check_stuff()
server.delete()
But this creates a new server for each set of parameters_from_parametrize. Is there a way to create one server, using the fixtures, and then run that server?
as in, for example:
server = Server(host,env, dns, random_name, random_passwd)
server.create()
@pytest.mark.parametrize(parameters_from_parametrize)
def test_something(server):
server.do_stuff(parameters_from_parametrize)
check_stuff()
server.delete()
This way server would only be created once. Example above doesn't work, since fixtures cannot be used before test functions (and the code outside test functions won't share the scope with them), so adding server outside of test function fails. I tried setup and teardown, but I cannot get it to work with fixtures.
Is there a way to do it? I thought I'd be able to do it using setup/teardown, or by creating a test class, but I failed.
I hope this is not an extremely noobish question, but it probably is.
Upvotes: 13
Views: 10528
Reputation: 34252
That's what fixtures are for:
@pytest.fixture(scope='session') # one server to rule'em all
def server():
server = Server(host, env, dns, random_name, random_passwd)
server.create()
return server
def test_something(server, ...):
# test logic
This can also be improved to shutdown the server after the tests complete:
@pytest.yield_fixture(scope='session')
def server():
server = Server(host,env, dns, random_name, random_passwd)
server.create()
yield server
server.delete()
In either case pytest will handle the server creation according to the defined scope and provide the server
argument to all test functions having it. That way, the server is created only once per testing session regardless of how many tests are using it, and how they are parameterised.
Upvotes: 19