Continue to call finalizers in the stack when a finalizer in a former scope raises an exception

This commit is contained in:
Guoqiang Zhang 2018-06-11 16:12:47 -04:00
parent 2a79f58ba3
commit a888bf182e
4 changed files with 29 additions and 1 deletions

View File

@ -82,6 +82,7 @@ Greg Price
Grig Gheorghiu Grig Gheorghiu
Grigorii Eremeev (budulianin) Grigorii Eremeev (budulianin)
Guido Wesdorp Guido Wesdorp
Guoqiang Zhang
Harald Armin Massa Harald Armin Massa
Henk-Jaap Wagenaar Henk-Jaap Wagenaar
Hugo van Kemenade 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) self._teardown_towards(needed_collectors)
def _teardown_towards(self, needed_collectors): def _teardown_towards(self, needed_collectors):
exc = None
while self.stack: while self.stack:
if self.stack == needed_collectors[:len(self.stack)]: if self.stack == needed_collectors[:len(self.stack)]:
break break
try:
self._pop_and_teardown() 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): def prepare(self, colitem):
""" setup objects along the collector chain to the test-method """ setup objects along the collector chain to the test-method

View File

@ -81,6 +81,23 @@ class TestSetupState(object):
ss._callfinalizers(item) ss._callfinalizers(item)
assert err.value.args == ("oops2",) 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):
ss.teardown_exact(item, None)
assert module_teardown
class BaseFunctionalTests(object): class BaseFunctionalTests(object):