Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module fixture runs before session fixtures if redefined #8074

Closed
voronind opened this issue Nov 25, 2020 · 5 comments
Closed

Module fixture runs before session fixtures if redefined #8074

voronind opened this issue Nov 25, 2020 · 5 comments
Labels
topic: fixtures anything involving fixtures directly or indirectly type: question general question, might be closed after 2 weeks of inactivity

Comments

@voronind
Copy link

If we have session fixture customer and redefine it with module scope, It can run after module fixtures.

tests/conftest.py

import pytest

@pytest.fixture(scope='session')
def customer():
    return 1

@pytest.fixture(scope='module')
def module_transaction():
    yield

tests/test_1.py

import pytest

@pytest.fixture(scope='module')
def customer(customer):
    return customer + 1

def test_1(module_transaction, customer):
    assert customer == 2
$ pytest tests --setup-only
============================= test session starts ==============================
platform linux -- Python 3.6.9, pytest-6.1.2, py-1.9.0, pluggy-0.13.1
rootdir: /home/voronin/projects/sintez_addons, configfile: setup.cfg
collected 1 item                                                               

test-module/test_1.py 
    SETUP    M module_transaction
SETUP    S customer
    SETUP    M customer (fixtures used: customer)
        tests/test_1.py::test_1 (fixtures used: customer, module_transaction)
    TEARDOWN M customer
    TEARDOWN M module_transaction
TEARDOWN S customer

============================ no tests ran in 0.01s =============================
@voronind
Copy link
Author

Related #5303

@asottile
Copy link
Member

this output seems correct to me, the scope of a fixture doesn't always indicate its ordering as they are only instantiated as needed. the scope of the fixture determines the lifetime of the fixture -- not the setup order

based on the parameters of your test, the first argument's fixture gets set up first

in your case you have a few choices if you want to force the ordering -- one is to reorder the parameters of your test such that customer is first -- another is to set autouse=True on your session fixture so it is always set up

@voronind
Copy link
Author

Documentation says that scope is about ordering. https://docs.pytest.org/en/stable/fixture.html#order-higher-scoped-fixtures-are-instantiated-first
In my case module_transaction is autouse and I can not reorder.

@voronind
Copy link
Author

If we define customer2 fixture we got other fixture lifetime.

tests/test_1.py

import pytest

@pytest.fixture(scope='module')
def customer2(customer):
    return customer + 1

def test_1(module_transaction, customer2):
    assert customer2 == 2
$ pytest tests --setup-only
Loading .env environment variables...
============================= test session starts ==============================
platform linux2 -- Python 2.7.15rc1, pytest-4.6.11, py-1.8.0, pluggy-0.13.0
rootdir: /home/voronin/projects/sintez_addons, inifile: setup.cfg
plugins: cov-2.10.0, flake8-1.0.4, forked-1.1.3, xdist-1.31.0
collected 1 item                                                               

tests/test_1.py 
SETUP    S customer
    SETUP    M module_transaction
    SETUP    M customer2 (fixtures used: customer)
        test-module/test_1.py::test_1 (fixtures used: customer, customer2, module_transaction)
    TEARDOWN M customer2
    TEARDOWN M module_transaction
TEARDOWN S customer

========================= no tests ran in 0.02 seconds =========================

@Zac-HD Zac-HD added topic: fixtures anything involving fixtures directly or indirectly type: question general question, might be closed after 2 weeks of inactivity labels Nov 27, 2020
@nicoddemus
Copy link
Member

Hi @voronind,

@asottile is correct, but your example is a bit different from the docs because your test is not requesting the customer/session fixture directly (as the documentation example shows), but indirectly through another fixture, customer/module, so that's the behavior we have currently.

  1. pytest determines it needs two fixtures to execute test_1: module_transaction and costumer, both module-scoped, so the order they will be created stays the same (if at that point we had a higher-scoped fixture, say "session", that would be created first);

  2. It creates module_transaction; it doesn't have any dependencies so that's that.

  3. It determines that costumer/module needs another fixture, costumer/session, so it instantiates it and passes it along to the costumer/module fixture function.

  4. With the result of the two fixtures, test_1 is executed with those parameters.

Currently we don't do a complete fixture resolution order before setting up things, but that's being discussed in #4871.

Closing this for now. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: fixtures anything involving fixtures directly or indirectly type: question general question, might be closed after 2 weeks of inactivity
Projects
None yet
Development

No branches or pull requests

4 participants