Skip to content

Commit 5a856b6

Browse files
author
Ryan Fitzpatrick
committed
handle and reraise subrequest finalizer exceptions
1 parent f0541b6 commit 5a856b6

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

_pytest/fixtures.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,16 @@ def addfinalizer(self, finalizer):
733733
self._finalizer.append(finalizer)
734734

735735
def finish(self):
736+
exceptions = []
736737
try:
737738
while self._finalizer:
738-
func = self._finalizer.pop()
739-
func()
739+
try:
740+
func = self._finalizer.pop()
741+
func()
742+
except:
743+
exceptions.append(sys.exc_info())
744+
if exceptions:
745+
py.builtin._reraise(*exceptions[0])
740746
finally:
741747
ihook = self._fixturemanager.session.ihook
742748
ihook.pytest_fixture_post_finalizer(fixturedef=self)

changelog/2440.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Exceptions in a SubRequest's finish() block are suppressed until all finalizers are called, with the initial exception reraised.

testing/python/fixture.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,32 @@ def test_second():
657657
"*1 error*" # XXX the whole module collection fails
658658
])
659659

660+
def test_request_subrequest_addfinalizer_exceptions(self, testdir):
661+
testdir.makepyfile("""
662+
import pytest
663+
l = []
664+
def _excepts():
665+
raise Exception('Error')
666+
@pytest.fixture
667+
def subrequest(request):
668+
return request
669+
@pytest.fixture
670+
def something(subrequest):
671+
subrequest.addfinalizer(lambda: l.append(1))
672+
subrequest.addfinalizer(lambda: l.append(2))
673+
subrequest.addfinalizer(_excepts)
674+
@pytest.fixture
675+
def excepts(subrequest):
676+
subrequest.addfinalizer(_excepts)
677+
subrequest.addfinalizer(lambda: l.append(3))
678+
def test_first(something, excepts):
679+
pass
680+
def test_second():
681+
assert l == [3, 2, 1]
682+
""")
683+
reprec = testdir.inline_run()
684+
reprec.assertoutcome(passed=2, failed=1)
685+
660686
def test_request_getmodulepath(self, testdir):
661687
modcol = testdir.getmodulecol("def test_somefunc(): pass")
662688
item, = testdir.genitems([modcol])

0 commit comments

Comments
 (0)