Merge pull request #3570 from sangongs/fix_stack_finalizer

Continue to call finalizers in the stack when a finalizer raises an exception
This commit is contained in:
Anthony Sottile 2018-06-11 19:07:59 -07:00 committed by GitHub
commit ef88251573
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 1 deletions

View File

@ -82,6 +82,7 @@ Greg Price
Grig Gheorghiu
Grigorii Eremeev (budulianin)
Guido Wesdorp
Guoqiang Zhang
Harald Armin Massa
Henk-Jaap Wagenaar
Hugo van Kemenade

View File

@ -0,0 +1 @@
Continue to call finalizers in the stack when a finalizer in a former scope raises an exception.

View File

@ -527,10 +527,19 @@ class SetupState(object):
self._teardown_towards(needed_collectors)
def _teardown_towards(self, needed_collectors):
exc = None
while self.stack:
if self.stack == needed_collectors[:len(self.stack)]:
break
self._pop_and_teardown()
try:
self._pop_and_teardown()
except TEST_OUTCOME:
# XXX Only first exception will be seen by user,
# ideally all should be reported.
if exc is None:
exc = sys.exc_info()
if exc:
py.builtin._reraise(*exc)
def prepare(self, colitem):
""" setup objects along the collector chain to the test-method

View File

@ -81,6 +81,24 @@ class TestSetupState(object):
ss._callfinalizers(item)
assert err.value.args == ("oops2",)
def test_teardown_multiple_scopes_one_fails(self, testdir):
module_teardown = []
def fin_func():
raise Exception("oops1")
def fin_module():
module_teardown.append("fin_module")
item = testdir.getitem("def test_func(): pass")
ss = runner.SetupState()
ss.addfinalizer(fin_module, item.listchain()[-2])
ss.addfinalizer(fin_func, item)
ss.prepare(item)
with pytest.raises(Exception, match="oops1"):
ss.teardown_exact(item, None)
assert module_teardown
class BaseFunctionalTests(object):