Ensure all finalizations are run when one fails

Fixes issue287.
This commit is contained in:
Floris Bruynooghe 2013-11-19 17:26:18 +00:00
parent 9b21d3f206
commit 72752165df
3 changed files with 28 additions and 1 deletions

View File

@ -1,6 +1,10 @@
Unreleased
-----------------------------------
- fix issue287 by running all finalizers but saving the exception
from the last failing finalizer and re-raising it so teardown will
still have failed.
- fix issue384 by removing the trial support code
since the unittest compat enhancements allow
trial to handle it on its own

View File

@ -328,9 +328,17 @@ class SetupState(object):
def _callfinalizers(self, colitem):
finalizers = self._finalizers.pop(colitem, None)
exc = None
while finalizers:
fin = finalizers.pop()
fin()
try:
fin()
except KeyboardInterrupt:
raise
except:
exc = py.std.sys.exc_info()
if exc:
py.builtin._reraise(*exc)
def _teardown_with_finalization(self, colitem):
self._callfinalizers(colitem)

View File

@ -43,6 +43,21 @@ class TestSetupState:
pytest.raises(ValueError, lambda: ss.prepare(item))
pytest.raises(ValueError, lambda: ss.prepare(item))
def test_teardown_multiple_one_fails(self, testdir):
r = []
def fin1(): r.append('fin1')
def fin2(): raise Exception('oops')
def fin3(): r.append('fin3')
item = testdir.getitem("def test_func(): pass")
ss = runner.SetupState()
ss.addfinalizer(fin1, item)
ss.addfinalizer(fin2, item)
ss.addfinalizer(fin3, item)
with pytest.raises(Exception) as err:
ss._callfinalizers(item)
assert err.value.args == ('oops',)
assert r == ['fin3', 'fin1']
class BaseFunctionalTests:
def test_passfunction(self, testdir):