pytest_fixture_post_finalizer now receives a request argument

This commit is contained in:
Bruno Oliveira 2017-11-12 11:14:55 -02:00
parent 258031afe5
commit 6550b9911b
3 changed files with 41 additions and 48 deletions

View File

@ -4,6 +4,7 @@ import inspect
import sys
import warnings
import functools
import py
from py._code.code import FormattedExcinfo
@ -521,7 +522,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
val = fixturedef.execute(request=subrequest)
finally:
# if fixture function failed it might have registered finalizers
self.session._setupstate.addfinalizer(fixturedef.finish,
self.session._setupstate.addfinalizer(functools.partial(fixturedef.finish, request=subrequest),
subrequest.node)
return val
@ -744,7 +745,7 @@ class FixtureDef:
def addfinalizer(self, finalizer):
self._finalizer.append(finalizer)
def finish(self):
def finish(self, request):
exceptions = []
try:
while self._finalizer:
@ -759,10 +760,12 @@ class FixtureDef:
py.builtin._reraise(*e)
finally:
hook = self._fixturemanager.session.config.hook
hook.pytest_fixture_post_finalizer(fixturedef=self)
hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
hook.pytest_fixture_post_finalizer(fixturedef=self, request=request)
# even if finalization fails, we invalidate
# the cached fixture value
# the cached fixture value and remove
# all finalizers because they may be bound methods which will
# keep instances alive
if hasattr(self, "cached_result"):
del self.cached_result
@ -772,7 +775,7 @@ class FixtureDef:
for argname in self.argnames:
fixturedef = request._get_active_fixturedef(argname)
if argname != "request":
fixturedef.addfinalizer(self.finish)
fixturedef.addfinalizer(functools.partial(self.finish, request=request))
my_cache_key = request.param_index
cached_result = getattr(self, "cached_result", None)
@ -788,9 +791,7 @@ class FixtureDef:
self.finish()
assert not hasattr(self, "cached_result")
hook = self._fixturemanager.session.gethookproxy(
request._pyfuncitem.fspath
)
hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
return hook.pytest_fixture_setup(fixturedef=self, request=request)
def __repr__(self):

View File

@ -296,7 +296,7 @@ def pytest_fixture_setup(fixturedef, request):
Stops at first non-None result, see :ref:`firstresult` """
def pytest_fixture_post_finalizer(fixturedef):
def pytest_fixture_post_finalizer(fixturedef, request):
""" called after fixture teardown, but before the cache is cleared so
the fixture result cache ``fixturedef.cached_result`` can
still be accessed."""

View File

@ -3127,49 +3127,41 @@ class TestParameterizedSubRequest(object):
""".format(fixfile.strpath, testfile.basename))
def test_pytest_fixture_setup_hook(testdir):
def test_pytest_fixture_setup_and_post_finalizer_hook(testdir):
testdir.makeconftest("""
import pytest
def pytest_fixture_setup():
print('pytest_fixture_setup hook called')
from __future__ import print_function
def pytest_fixture_setup(fixturedef, request):
print('ROOT setup hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
def pytest_fixture_post_finalizer(fixturedef, request):
print('ROOT finalizer hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
""")
testdir.makepyfile("""
import pytest
testdir.makepyfile(**{
'tests/conftest.py': """
from __future__ import print_function
def pytest_fixture_setup(fixturedef, request):
print('TESTS setup hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
def pytest_fixture_post_finalizer(fixturedef, request):
print('TESTS finalizer hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
""",
'tests/test_hooks.py': """
from __future__ import print_function
import pytest
@pytest.fixture()
def some():
return 'some'
@pytest.fixture()
def my_fixture():
return 'some'
def test_func(some):
assert some == 'some'
""")
def test_func(my_fixture):
print('TEST test_func')
assert my_fixture == 'some'
"""
})
result = testdir.runpytest("-s")
assert result.ret == 0
result.stdout.fnmatch_lines([
"*pytest_fixture_setup hook called*",
])
def test_pytest_fixture_post_finalizer_hook(testdir):
testdir.makeconftest("""
import pytest
def pytest_fixture_post_finalizer():
print('pytest_fixture_post_finalizer hook called')
""")
testdir.makepyfile("""
import pytest
@pytest.fixture()
def some():
return 'some'
def test_func(some):
assert some == 'some'
""")
result = testdir.runpytest("-s")
assert result.ret == 0
result.stdout.fnmatch_lines([
"*pytest_fixture_post_finalizer hook called*",
"*TESTS setup hook called for my_fixture from test_func*",
"*ROOT setup hook called for my_fixture from test_func*",
"*TEST test_func*",
"*TESTS finalizer hook called for my_fixture from test_func*",
"*ROOT finalizer hook called for my_fixture from test_func*",
])