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

Exception in SubRequest finalizer prevents further registered SubRequest finalizer calls #2440

Closed
rmfitzpatrick opened this Issue May 26, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@rmfitzpatrick
Copy link
Contributor

rmfitzpatrick commented May 26, 2017

When an exception occurs in a SubRequest's registered finalizer, no further registered finalizers are invoked, causing incomplete teardown. This is not the case for FixtureRequests:

import pytest


class Factory(object):

    @classmethod
    def __call__(cls, request, to_teardown):
        def teardown():
            print 'in ', teardown, request, to_teardown
            to_teardown()
        print 'register', teardown, request, to_teardown
        request.addfinalizer(teardown)


@pytest.fixture
def factory(request):
    def _factory(to_teardown):
        return Factory()(request, to_teardown)
    return _factory


def _in(num):
    print '_in({0})'.format(num)
    raise Exception(num)


def one():
    _in('one')


def two():
    _in('two')


def test_with_factory_and_fixturerequest(request):
    factory = Factory()
    for to_teardown in (one, two):
        factory(request, to_teardown)


def test_with_factory_and_subrequest(factory):
    for to_teardown in (one, two):
        factory(to_teardown)
(pytest) user$ pytest -vs test.py
====================================================================================== test session starts =======================================================================================
platform darwin -- Python 2.7.13, pytest-3.1.1.dev23+g7950c26, py-1.4.33, pluggy-0.4.0 -- /.virtualenvs/pytest/bin/python2.7
cachedir: .cache
rootdir: user, inifile:
plugins: hypothesis-3.11.0
collected 2 items

test.py::test_with_factory_and_fixturerequest register <function teardown at 0x110e6d2a8> <FixtureRequest for <Function 'test_with_factory_and_fixturerequest'>> <function one at 0x110e37e60>
register <function teardown at 0x110e6d320> <FixtureRequest for <Function 'test_with_factory_and_fixturerequest'>> <function two at 0x110e37ed8>
PASSEDin  <function teardown at 0x110e6d320> <FixtureRequest for <Function 'test_with_factory_and_fixturerequest'>> <function two at 0x110e37ed8>
_in(two)
in  <function teardown at 0x110e6d2a8> <FixtureRequest for <Function 'test_with_factory_and_fixturerequest'>> <function one at 0x110e37e60>
_in(one)

test.py::test_with_factory_and_fixturerequest ERROR
test.py::test_with_factory_and_subrequest register <function teardown at 0x110e6d320> <SubRequest 'factory' for <Function 'test_with_factory_and_subrequest'>> <function one at 0x110e37e60>
register <function teardown at 0x110e6d2a8> <SubRequest 'factory' for <Function 'test_with_factory_and_subrequest'>> <function two at 0x110e37ed8>
PASSEDin  <function teardown at 0x110e6d2a8> <SubRequest 'factory' for <Function 'test_with_factory_and_subrequest'>> <function two at 0x110e37ed8>
_in(two)

test.py::test_with_factory_and_subrequest ERROR

============================================================================================= ERRORS =============================================================================================
___________________________________________________________________ ERROR at teardown of test_with_factory_and_fixturerequest ____________________________________________________________________

    def teardown():
        print 'in ', teardown, request, to_teardown
>       to_teardown()

test.py:14:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
test.py:41: in two
    _in('two')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

num = 'two'

    def _in(num):
        print '_in({0})'.format(num)
>       raise Exception(num)
E       Exception: two

test.py:33: Exception
_____________________________________________________________________ ERROR at teardown of test_with_factory_and_subrequest ______________________________________________________________________

    def teardown():
        print 'in ', teardown, request, to_teardown
>       to_teardown()

test.py:14:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
test.py:41: in two
    _in('two')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

num = 'two'

    def _in(num):
        print '_in({0})'.format(num)
>       raise Exception(num)
E       Exception: two

test.py:33: Exception
=============================================================================== 2 passed, 2 error in 0.03 seconds ================================================================================

Notice in test_with_factory_and_fixturerequest that both registered finalizers are invoked but in test_with_factory_and_subrequest only two() is. A workaround is to wrap any teardown calls that can potentially raise exceptions in a try/except, but this isn't ideal since the exceptions are informative.

(pytest) user$ pip list
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
appdirs (1.4.3)
enum34 (1.1.6)
hypothesis (3.11.0)
packaging (16.8)
pip (9.0.1)
py (1.4.33)
pyparsing (2.2.0)
pytest (3.1.1.dev23+g7950c26, /user/pytest)
setuptools (35.0.2)
six (1.10.0)
wheel (0.30.0a0)

edit: removed unnecessary functions

@rmfitzpatrick rmfitzpatrick changed the title Exception in SubRequest finalizer prevents further finalizer registered SubRequest calls Exception in SubRequest finalizer prevents further registered SubRequest finalizer calls May 26, 2017

@nicoddemus

This comment has been minimized.

Copy link
Member

nicoddemus commented May 26, 2017

Thanks for the report, appreciate the through description and example! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.