Skip to content

Multiple invocations of class-scoped fixture change called finalizer order #2495

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

Closed
rmfitzpatrick opened this issue Jun 12, 2017 · 5 comments
Labels
topic: fixtures anything involving fixtures directly or indirectly type: bug problem that needs to be addressed

Comments

@rmfitzpatrick
Copy link

rmfitzpatrick commented Jun 12, 2017

I'm running into some undesired teardown ordering in pytest 3.1.2.

import pytest

order_called = []

@pytest.fixture(scope='class')
def uses_request(request):
    def _uses_request(x):
        request.addfinalizer(lambda: order_called.append(x))

    for name in ('first', 'second'):
         _uses_request('uses_request: {}'.format(name))


@pytest.fixture(scope='class')
def subrequest(request):
    return request


class TestClassOne(object):

    def test_one(self, uses_request, subrequest):
        def uses_subrequest(name):
            subrequest.addfinalizer(lambda: order_called.append('uses_subrequest: {}'.format(name)))

        for name in ('first', 'second'):
            uses_subrequest(name)

    def test_two(self, uses_request, request):
        def in_test_uses_request(x):
            request.addfinalizer(lambda: order_called.append(x))

        for name in ('third', 'fourth'):
            in_test_uses_request('uses_request: {}'.format(name))


def test_order():
    assert order_called == ['uses_request: fourth',
                            'uses_request: third',
                            'uses_subrequest: second',
                            'uses_subrequest: first',
                            'uses_request: second',
                            'uses_request: first']
    def test_order():
>       assert order_called == ['uses_request: fourth',
                                'uses_request: third',
                                'uses_subrequest: second',
                                'uses_subrequest: first',
                                'uses_request: second',
                                'uses_request: first']
E       AssertionError: assert ['uses_reques...quest: first'] == ['uses_request...quest: first']
E         At index 2 diff: 'uses_request: second' != 'uses_subrequest: second'
E         Use -v to get the full diff

tmp.py:36: AssertionError
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> entering PDB >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> /tmp/tmp.py(36)test_order()
-> assert order_called == ['uses_request: fourth',
(Pdb) pp order_called
['uses_request: fourth',
 'uses_request: third',
 'uses_request: second',
 'uses_request: first',
 'uses_subrequest: second',
 'uses_subrequest: first']

If I remove the uses_request parameter from test_two then the tests pass, but this prevents me being able to run test_two on its own (mark.usefixtures('uses_request') also triggers the unwanted behavior). Is my expectation that finalizer calls should always be lifo correct? I'd think that the presence of multiple uses_request should behave no differently than it appearing once.

By having the teardown functions not occur in the order of finalizer registration my tests error in product-specific ways I cannot account for without losing desired coverage.

@nicoddemus nicoddemus added the topic: fixtures anything involving fixtures directly or indirectly label Sep 28, 2017
@nicoddemus
Copy link
Member

Is my expectation that finalizer calls should always be lifo correct?

I'm not sure out of my head, I would have to take a look at the code. @RonnyPfannschmidt do you know this promptly and can answer perhaps?

@RonnyPfannschmidt
Copy link
Member

Nope

@TheDesertKing
Copy link

I believe this issue was addressed on issue #3678, might wanna close it.

@RonnyPfannschmidt
Copy link
Member

returning to this now

finalisers belong to requests

requests clean up in fixture order (each request is per fixture)

the expectation of @rmfitzpatrick was wrong and pytest indeed correctly tears down the requests in order,

starting with the function scoped one

then following the class scoped ones in reverse creation order

#3674 is completely unrelated

@RonnyPfannschmidt
Copy link
Member

closing as not a bug

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: bug problem that needs to be addressed
Projects
None yet
Development

No branches or pull requests

4 participants