Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share object from fixture to all tests using pytest?

Tags:

python

pytest

What is the best way to define an object in a fixture with session scope and autouse=True, so it will be available to all tests?

@pytest.fixture(scope='session', autouse=True)
def setup_func(request):
    obj = SomeObj()

Next thing, I want some magic that previously created obj will appear in each test context without the need of each test to define the setup_func fixture.

def test_one():
   obj.do_something_fancy()
like image 791
alnet Avatar asked Nov 11 '15 15:11

alnet


People also ask

Where do I put shared pytest fixtures?

You can put fixtures into individual test files, but to share fixtures among multiple test files, you need to use a conftest.py file somewhere centrally located for all of the tests. For the Tasks project, all of the fixtures will be in tasks_proj/tests/conftest.py.

How do you call pytest fixture directly?

To access the fixture function, the tests have to mention the fixture name as input parameter. Pytest while the test is getting executed, will see the fixture name as input parameter. It then executes the fixture function and the returned value is stored to the input parameter, which can be used by the test.

Can pytest fixtures use other fixtures?

A fixture can use multiple other fixtures. Just like a test method can take multiple fixtures as arguments, a fixture can take multiple other fixtures as arguments and use them to create the fixture value that it returns.

Which decorator is used for tests using multiple fixtures pytest?

The first and easiest way to instantiate some dataset is to use pytest fixtures. pytest. fixture decorator makes it possible to inject the return value in the test functions whose have in their signature the decorated function name.


2 Answers

My recommendation would to add the fixture to conftest.py and make sure to return the object you want to produce from the fixture.

As noted, this makes "autouse" kind of useless.

In the root directory for your tests, add the fixture to a file named conftest.py:

@pytest.fixture(scope='session', autouse=True)
def someobj(request):
    return SomeObj()

Any test file beneath the root file will have access to this fixture (for example test_foo.py):

def test_foo(someobj):
    assert isinstance(someobj, SomeObj)

Another approach, would be to use a global variable defined in the same test or imported from a module.

For example in conftest.py:

someobj = None
@pytest.fixture(scope='session', autouse=True)
def prep_someobj(request):
    someobj = SomeObj()

Then in your test:

from . import conftest

def test_foo():
    assert isinstance(conftest.someobj, SomeObj)

In my opinion this is less readable and more cumbersome than the first method.

like image 55
Sebastian Avatar answered Sep 20 '22 21:09

Sebastian


A more general pattern for this is to return locals() at the end of your conftest and you'll be able to easily reference anything created in the fixture.

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()
like image 28
Everett Toews Avatar answered Sep 22 '22 21:09

Everett Toews