Skip to content

Commit

Permalink
Merge pull request #3570 from sangongs/fix_stack_finalizer
Browse files Browse the repository at this point in the history
Continue to call finalizers in the stack when a finalizer raises an exception
  • Loading branch information
asottile authored Jun 12, 2018
2 parents 04b65cf + 4112596 commit ef88251
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Greg Price
Grig Gheorghiu
Grigorii Eremeev (budulianin)
Guido Wesdorp
Guoqiang Zhang
Harald Armin Massa
Henk-Jaap Wagenaar
Hugo van Kemenade
Expand Down
1 change: 1 addition & 0 deletions changelog/3569.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Continue to call finalizers in the stack when a finalizer in a former scope raises an exception.
11 changes: 10 additions & 1 deletion src/_pytest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,10 +527,19 @@ def teardown_exact(self, item, nextitem):
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
Expand Down
18 changes: 18 additions & 0 deletions testing/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ def fin2():
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):

Expand Down

0 comments on commit ef88251

Please sign in to comment.