How to have two issued fixtures depend on each other?

Viewed 1833

In test_something(), the app instance should be the same as used by the login instance.

@pytest.fixture
def app():
    # ...
    return app

@pytest.fixture
def login(app):
    # ...
    return login

def test_something(self, app, login):
    pass

What I tried is returning both objects from the second fixture, but I wouldn't call this idiomatic.

@pytest.fixture
def app_and_login(app):
    # ...
    return app, login

def test_something(self, app_and_login):
    app, login = login_and_login

Is there a better way to do this?

4 Answers

I know this question is old, but I'm not seeing the behavior you describe, and I got really sidetracked by this Q&A until I thought, "It can't work that way..." and tested it out for myself. I tried this on:

platform darwin -- Python 3.7.7, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 -- .../bin/python3

I made this test, and it passes:

import collections
import pytest

AppObject = collections.namedtuple("App", ["name", "login"])

@pytest.fixture
def app():
    app = AppObject("appname", "applogin")
    return app

@pytest.fixture
def login(app):
    return app.login

def test_something(app, login):
    assert isinstance(app, AppObject) and app.name == "appname"
    assert isinstance(login, str) and login == "applogin"

OP seems concerned about the app object being received by the login fixture being different from the app returned by the app fixture. I don't see that happening. For instance, if you add some helpful print statements like this:

import collections
import pytest

AppObject = collections.namedtuple("App", ["name", "login"])

@pytest.fixture
def app():
    app = AppObject("appname", "applogin")
    print("Object id in app fixture: %d" % id(app))
    return app

@pytest.fixture
def login(app):
    print("Object id in login fixture: %d" % id(app))
    return app.login

def test_something(app, login):
    print("Object id in test: %d" % id(app))
    assert isinstance(app, AppObject) and app.name == "appname"
    assert isinstance(login, str) and login == "applogin"

I see this output:

Object id in app fixture: 4451368624
Object id in login fixture: 4451368624
Object id in test: 4451368624

...so it's definitely the same object in all three places. Nested fixtures like this "just work" for me, so I'm either missing the point of the question you were asking, or behavior has changed, or... something else. But I wanted to leave this here for others who come along looking for nested/dependent fixtures like this.

Related