SO-17664702: call fixture finalizers even if the fixture function

partially failed (finalizers would not always be called before)
This commit is contained in:
holger krekel 2013-07-17 10:29:11 +02:00
parent c53556b88d
commit 1280add047
5 changed files with 52 additions and 10 deletions

View File

@ -1,6 +1,9 @@
Changes between 2.3.5 and 2.4.DEV
-----------------------------------
- SO-17664702: call fixture finalizers even if the fixture function
partially failed (finalizers would not always be called before)
- color the last line red or green depending if failures/errors occured
or everything passed. thanks Christian Theunert.

View File

@ -1,2 +1,2 @@
#
__version__ = '2.4.0.dev6'
__version__ = '2.4.0.dev7'

View File

@ -1290,15 +1290,21 @@ class FixtureRequest(FuncargnamesCompatAttr):
# route request.addfinalizer to fixturedef
mp.setattr(self, "addfinalizer", fixturedef.addfinalizer)
try:
# perform the fixture call
val = fixturedef.execute(request=self)
finally:
# if the fixture function failed it might still have
# registered finalizers so we can register
# prepare finalization according to scope
# (XXX analyse exact finalizing mechanics / cleanup)
self.session._setupstate.addfinalizer(fixturedef.finish, self.node)
self.session._setupstate.addfinalizer(fixturedef.finish,
self.node)
self._fixturemanager.addargfinalizer(fixturedef.finish, argname)
for subargname in fixturedef.argnames: # XXX all deps?
self._fixturemanager.addargfinalizer(fixturedef.finish, subargname)
self._fixturemanager.addargfinalizer(fixturedef.finish,
subargname)
mp.undo()
return val

View File

@ -12,7 +12,7 @@ def main():
name='pytest',
description='py.test: simple powerful testing with Python',
long_description = long_description,
version='2.4.0.dev6',
version='2.4.0.dev7',
url='http://pytest.org',
license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

View File

@ -309,6 +309,39 @@ class TestRequestBasic:
print(ss.stack)
assert teardownlist == [1]
def test_request_addfinalizer_failing_setup(self, testdir):
testdir.makepyfile("""
import pytest
l = [1]
@pytest.fixture
def myfix(request):
request.addfinalizer(l.pop)
assert 0
def test_fix(myfix):
pass
def test_finalizer_ran():
assert not l
""")
reprec = testdir.inline_run("-s")
reprec.assertoutcome(failed=1, passed=1)
def test_request_addfinalizer_failing_setup_module(self, testdir):
testdir.makepyfile("""
import pytest
l = [1, 2]
@pytest.fixture(scope="module")
def myfix(request):
request.addfinalizer(l.pop)
request.addfinalizer(l.pop)
assert 0
def test_fix(myfix):
pass
""")
reprec = testdir.inline_run("-s")
mod = reprec.getcalls("pytest_runtest_setup")[0].item.module
assert not mod.l
def test_request_addfinalizer_partial_setup_failure(self, testdir):
p = testdir.makepyfile("""
l = []