Cache exception raised in fixtures according to their scope
Without this if a session scoped fixture fails it's setup it will be re-tried each time it is requested. Especially in case of skip or failure exceptions this can be undesirable, but caching makes sense for all exceptions.
This commit is contained in:
parent
65a145e2a7
commit
c46e2cbbc7
|
@ -1,6 +1,8 @@
|
||||||
NEXT (2.6)
|
NEXT (2.6)
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
- Cache exceptions from fixtures according to their scope (issue 467).
|
||||||
|
|
||||||
- fix issue514: teach assertion reinterpretation about private class attributes
|
- fix issue514: teach assertion reinterpretation about private class attributes
|
||||||
|
|
||||||
- change -v output to include full node IDs of tests. Users can copy
|
- change -v output to include full node IDs of tests. Users can copy
|
||||||
|
@ -59,10 +61,6 @@ NEXT (2.6)
|
||||||
|
|
||||||
- fix issue483: trial/py33 works now properly. Thanks Daniel Grana for PR.
|
- fix issue483: trial/py33 works now properly. Thanks Daniel Grana for PR.
|
||||||
|
|
||||||
- improve example for pytest integration with "python setup.py test"
|
|
||||||
which now has a generic "-a" or "--pytest-args" option where you
|
|
||||||
can pass additional options as a quoted string. Thanks Trevor Bekolay.
|
|
||||||
|
|
||||||
- simplified internal capturing mechanism and made it more robust
|
- simplified internal capturing mechanism and made it more robust
|
||||||
against tests or setups changing FD1/FD2, also better integrated
|
against tests or setups changing FD1/FD2, also better integrated
|
||||||
now with pytest.pdb() in single tests.
|
now with pytest.pdb() in single tests.
|
||||||
|
@ -89,9 +87,6 @@ NEXT (2.6)
|
||||||
functions, including unittest-style Classes. If set to False, the
|
functions, including unittest-style Classes. If set to False, the
|
||||||
test will not be collected.
|
test will not be collected.
|
||||||
|
|
||||||
- fix issue512: show "<notset>" for arguments which might not be set
|
|
||||||
in monkeypatch plugin. Improves output in documentation.
|
|
||||||
|
|
||||||
|
|
||||||
2.5.2
|
2.5.2
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
|
@ -1337,7 +1337,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
||||||
except FixtureLookupError:
|
except FixtureLookupError:
|
||||||
if argname == "request":
|
if argname == "request":
|
||||||
class PseudoFixtureDef:
|
class PseudoFixtureDef:
|
||||||
cached_result = (self, [0])
|
cached_result = (self, [0], None)
|
||||||
return PseudoFixtureDef
|
return PseudoFixtureDef
|
||||||
raise
|
raise
|
||||||
result = self._getfuncargvalue(fixturedef)
|
result = self._getfuncargvalue(fixturedef)
|
||||||
|
@ -1810,7 +1810,7 @@ class FixtureDef:
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
for argname in self.argnames:
|
for argname in self.argnames:
|
||||||
fixturedef = request._get_active_fixturedef(argname)
|
fixturedef = request._get_active_fixturedef(argname)
|
||||||
result, arg_cache_key = fixturedef.cached_result
|
result, arg_cache_key, exc = fixturedef.cached_result
|
||||||
kwargs[argname] = result
|
kwargs[argname] = result
|
||||||
if argname != "request":
|
if argname != "request":
|
||||||
fixturedef.addfinalizer(self.finish)
|
fixturedef.addfinalizer(self.finish)
|
||||||
|
@ -1818,13 +1818,12 @@ class FixtureDef:
|
||||||
my_cache_key = request.param_index
|
my_cache_key = request.param_index
|
||||||
cached_result = getattr(self, "cached_result", None)
|
cached_result = getattr(self, "cached_result", None)
|
||||||
if cached_result is not None:
|
if cached_result is not None:
|
||||||
#print argname, "Found cached_result", cached_result
|
result, cache_key, err = cached_result
|
||||||
#print argname, "param_index", param_index
|
|
||||||
result, cache_key = cached_result
|
|
||||||
if my_cache_key == cache_key:
|
if my_cache_key == cache_key:
|
||||||
#print request.fixturename, "CACHE HIT", repr(my_cache_key)
|
if err is not None:
|
||||||
return result
|
py.builtin._reraise(*err)
|
||||||
#print request.fixturename, "CACHE MISS"
|
else:
|
||||||
|
return result
|
||||||
# we have a previous but differently parametrized fixture instance
|
# we have a previous but differently parametrized fixture instance
|
||||||
# so we need to tear it down before creating a new one
|
# so we need to tear it down before creating a new one
|
||||||
self.finish()
|
self.finish()
|
||||||
|
@ -1841,9 +1840,13 @@ class FixtureDef:
|
||||||
fixturefunc = getimfunc(self.func)
|
fixturefunc = getimfunc(self.func)
|
||||||
if fixturefunc != self.func:
|
if fixturefunc != self.func:
|
||||||
fixturefunc = fixturefunc.__get__(request.instance)
|
fixturefunc = fixturefunc.__get__(request.instance)
|
||||||
result = call_fixture_func(fixturefunc, request, kwargs,
|
try:
|
||||||
self.yieldctx)
|
result = call_fixture_func(fixturefunc, request, kwargs,
|
||||||
self.cached_result = (result, my_cache_key)
|
self.yieldctx)
|
||||||
|
except Exception:
|
||||||
|
self.cached_result = (None, my_cache_key, sys.exc_info())
|
||||||
|
raise
|
||||||
|
self.cached_result = (result, my_cache_key, None)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
|
@ -1430,6 +1430,25 @@ class TestFixtureMarker:
|
||||||
reprec = testdir.inline_run()
|
reprec = testdir.inline_run()
|
||||||
reprec.assertoutcome(passed=3)
|
reprec.assertoutcome(passed=3)
|
||||||
|
|
||||||
|
def test_scope_session_exc(self, testdir):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
l = []
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def fix():
|
||||||
|
l.append(1)
|
||||||
|
pytest.skip('skipping')
|
||||||
|
|
||||||
|
def test_1(fix):
|
||||||
|
pass
|
||||||
|
def test_2(fix):
|
||||||
|
pass
|
||||||
|
def test_last():
|
||||||
|
assert l == [1]
|
||||||
|
""")
|
||||||
|
reprec = testdir.inline_run()
|
||||||
|
reprec.assertoutcome(skipped=2, passed=1)
|
||||||
|
|
||||||
def test_scope_module_uses_session(self, testdir):
|
def test_scope_module_uses_session(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
Loading…
Reference in New Issue