Merge pytest-2.7 for issue660 fix

This commit is contained in:
Floris Bruynooghe 2015-04-13 00:04:53 +01:00
commit 09dff73607
3 changed files with 52 additions and 16 deletions

View File

@ -2,6 +2,20 @@
-----------------------------
2.7.1.dev (compared to 2.7.0)
-----------------------------
- fix issue660: properly report scope-mismatch-access errors
independently from ordering of fixture arguments. Also
avoid the pytest internal traceback which does not provide
information to the user. Thanks Holger Krekel.
- streamlined and documented release process. Also all versions
(in setup.py and documentation generation) are now read
from _pytest/__init__.py. Thanks Holger Krekel.
- fixed docs to remove the notion that yield-fixtures are experimental.
They are here to stay :) Thanks Bruno Oliveira.
- Support building wheels by using environment markers for the
requirements. Thanks Ionel Maries Cristian.

View File

@ -1356,12 +1356,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
try:
val = cache[cachekey]
except KeyError:
__tracebackhide__ = True
if scopemismatch(self.scope, scope):
raise ScopeMismatchError("You tried to access a %r scoped "
"resource with a %r scoped request object" %(
(scope, self.scope)))
__tracebackhide__ = False
self._check_scope(self.fixturename, self.scope, scope)
val = setup()
cache[cachekey] = val
if teardown is not None:
@ -1392,6 +1387,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
if argname == "request":
class PseudoFixtureDef:
cached_result = (self, [0], None)
scope = "function"
return PseudoFixtureDef
raise
# remove indent to prevent the python3 exception
@ -1435,16 +1431,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
subrequest = SubRequest(self, scope, param, param_index, fixturedef)
# check if a higher-level scoped fixture accesses a lower level one
if scope is not None:
__tracebackhide__ = True
if scopemismatch(self.scope, scope):
# try to report something helpful
lines = subrequest._factorytraceback()
raise ScopeMismatchError("You tried to access the %r scoped "
"fixture %r with a %r scoped request object, "
"involved factories\n%s" %(
(scope, argname, self.scope, "\n".join(lines))))
__tracebackhide__ = False
subrequest._check_scope(argname, self.scope, scope)
# clear sys.exc_info before invoking the fixture (python bug?)
# if its not explicitly cleared it will leak into the call
@ -1458,6 +1445,18 @@ class FixtureRequest(FuncargnamesCompatAttr):
subrequest.node)
return val
def _check_scope(self, argname, invoking_scope, requested_scope):
if argname == "request":
return
if scopemismatch(invoking_scope, requested_scope):
# try to report something helpful
lines = self._factorytraceback()
pytest.fail("ScopeMismatch: you tried to access the %r scoped "
"fixture %r with a %r scoped request object, "
"involved factories\n%s" %(
(requested_scope, argname, invoking_scope, "\n".join(lines))),
pytrace=False)
def _factorytraceback(self):
lines = []
for fixturedef in self._get_fixturestack():
@ -1518,6 +1517,7 @@ scopenum_function = scopes.index("function")
def scopemismatch(currentscope, newscope):
return scopes.index(newscope) > scopes.index(currentscope)
class FixtureLookupError(LookupError):
""" could not return a requested Fixture (missing or invalid). """
def __init__(self, argname, request, msg=None):
@ -1867,6 +1867,7 @@ class FixtureDef:
for argname in self.argnames:
fixturedef = request._get_active_fixturedef(argname)
result, arg_cache_key, exc = fixturedef.cached_result
request._check_scope(argname, request.scope, fixturedef.scope)
kwargs[argname] = result
if argname != "request":
fixturedef.addfinalizer(self.finish)

View File

@ -906,6 +906,27 @@ class TestFixtureUsages:
"*1 error*"
])
def test_receives_funcargs_scope_mismatch_issue660(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture(scope="function")
def arg1():
return 1
@pytest.fixture(scope="module")
def arg2(arg1):
return arg1 + 1
def test_add(arg1, arg2):
assert arg2 == 2
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines([
"*ScopeMismatch*involved factories*",
"* def arg2*",
"*1 error*"
])
def test_funcarg_parametrized_and_used_twice(self, testdir):
testdir.makepyfile("""
import pytest