Merge pull request #2496 from rmfitzpatrick/pytest2440_handle_subrequest_finalizer_exceptions
Handle exceptions in subrequest finalizers
This commit is contained in:
commit
336cf3e1f5
|
@ -733,10 +733,19 @@ class FixtureDef:
|
|||
self._finalizer.append(finalizer)
|
||||
|
||||
def finish(self):
|
||||
exceptions = []
|
||||
try:
|
||||
while self._finalizer:
|
||||
func = self._finalizer.pop()
|
||||
func()
|
||||
try:
|
||||
func = self._finalizer.pop()
|
||||
func()
|
||||
except:
|
||||
exceptions.append(sys.exc_info())
|
||||
if exceptions:
|
||||
e = exceptions[0]
|
||||
del exceptions # ensure we don't keep all frames alive because of the traceback
|
||||
py.builtin._reraise(*e)
|
||||
|
||||
finally:
|
||||
ihook = self._fixturemanager.session.ihook
|
||||
ihook.pytest_fixture_post_finalizer(fixturedef=self)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Exceptions raised during teardown by finalizers are now suppressed until all finalizers are called, with the initial exception reraised.
|
|
@ -657,6 +657,39 @@ class TestRequestBasic(object):
|
|||
"*1 error*" # XXX the whole module collection fails
|
||||
])
|
||||
|
||||
def test_request_subrequest_addfinalizer_exceptions(self, testdir):
|
||||
"""
|
||||
Ensure exceptions raised during teardown by a finalizer are suppressed
|
||||
until all finalizers are called, re-raising the first exception (#2440)
|
||||
"""
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
l = []
|
||||
def _excepts(where):
|
||||
raise Exception('Error in %s fixture' % where)
|
||||
@pytest.fixture
|
||||
def subrequest(request):
|
||||
return request
|
||||
@pytest.fixture
|
||||
def something(subrequest):
|
||||
subrequest.addfinalizer(lambda: l.append(1))
|
||||
subrequest.addfinalizer(lambda: l.append(2))
|
||||
subrequest.addfinalizer(lambda: _excepts('something'))
|
||||
@pytest.fixture
|
||||
def excepts(subrequest):
|
||||
subrequest.addfinalizer(lambda: _excepts('excepts'))
|
||||
subrequest.addfinalizer(lambda: l.append(3))
|
||||
def test_first(something, excepts):
|
||||
pass
|
||||
def test_second():
|
||||
assert l == [3, 2, 1]
|
||||
""")
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*Exception: Error in excepts fixture',
|
||||
'* 2 passed, 1 error in *',
|
||||
])
|
||||
|
||||
def test_request_getmodulepath(self, testdir):
|
||||
modcol = testdir.getmodulecol("def test_somefunc(): pass")
|
||||
item, = testdir.genitems([modcol])
|
||||
|
|
Loading…
Reference in New Issue