Explain a bad scope value to the user

This commit is contained in:
Tyler Goodlet 2016-09-06 14:16:25 -04:00
parent 7660a19d0a
commit 6db2f315fa
6 changed files with 55 additions and 4 deletions

View File

@ -127,6 +127,7 @@ Ted Xiao
Thomas Grainger Thomas Grainger
Tom Viner Tom Viner
Trevor Bekolay Trevor Bekolay
Tyler Goodlet
Vasily Kuznetsov Vasily Kuznetsov
Wouter van Ackooy Wouter van Ackooy
Xuecong Liao Xuecong Liao

View File

@ -16,18 +16,21 @@
in Python 3 (`#1944`_). in Python 3 (`#1944`_).
Thanks `@axil`_ for the PR. Thanks `@axil`_ for the PR.
* * Explain a bad scope value passed to ``@fixture`` declarations or
a ``MetaFunc.parametrize()`` call. Thanks `@tgoodlet`_ for the PR.
.. _@philpep: https://github.com/philpep .. _@philpep: https://github.com/philpep
.. _@raquel-ucl: https://github.com/raquel-ucl .. _@raquel-ucl: https://github.com/raquel-ucl
.. _@axil: https://github.com/axil .. _@axil: https://github.com/axil
.. _@tgoodlet: https://github.com/tgoodlet
.. _#1905: https://github.com/pytest-dev/pytest/issues/1905 .. _#1905: https://github.com/pytest-dev/pytest/issues/1905
.. _#1934: https://github.com/pytest-dev/pytest/issues/1934 .. _#1934: https://github.com/pytest-dev/pytest/issues/1934
.. _#1944: https://github.com/pytest-dev/pytest/issues/1944 .. _#1944: https://github.com/pytest-dev/pytest/issues/1944
3.0.2 3.0.2
===== =====

View File

@ -599,12 +599,29 @@ class ScopeMismatchError(Exception):
which has a lower scope (e.g. a Session one calls a function one) which has a lower scope (e.g. a Session one calls a function one)
""" """
scopes = "session module class function".split() scopes = "session module class function".split()
scopenum_function = scopes.index("function") scopenum_function = scopes.index("function")
def scopemismatch(currentscope, newscope): def scopemismatch(currentscope, newscope):
return scopes.index(newscope) > scopes.index(currentscope) return scopes.index(newscope) > scopes.index(currentscope)
def scope2index(scope, descr, where=None):
"""Look up the index of ``scope`` and raise a descriptive value error
if not defined.
"""
try:
return scopes.index(scope)
except ValueError:
raise ValueError(
"{0} {1}has an unsupported scope value '{2}'".format(
descr, 'from {0} '.format(where) if where else '',
scope)
)
class FixtureLookupError(LookupError): class FixtureLookupError(LookupError):
""" could not return a requested Fixture (missing or invalid). """ """ could not return a requested Fixture (missing or invalid). """
def __init__(self, argname, request, msg=None): def __init__(self, argname, request, msg=None):
@ -703,6 +720,7 @@ def call_fixture_func(fixturefunc, request, kwargs):
res = fixturefunc(**kwargs) res = fixturefunc(**kwargs)
return res return res
class FixtureDef: class FixtureDef:
""" A container for a factory definition. """ """ A container for a factory definition. """
def __init__(self, fixturemanager, baseid, argname, func, scope, params, def __init__(self, fixturemanager, baseid, argname, func, scope, params,
@ -713,7 +731,11 @@ class FixtureDef:
self.func = func self.func = func
self.argname = argname self.argname = argname
self.scope = scope self.scope = scope
self.scopenum = scopes.index(scope or "function") self.scopenum = scope2index(
scope or "function",
descr='fixture {0}'.format(func.__name__),
where=baseid
)
self.params = params self.params = params
startindex = unittest and 1 or None startindex = unittest and 1 or None
self.argnames = getfuncargnames(func, startindex=startindex) self.argnames = getfuncargnames(func, startindex=startindex)

View File

@ -770,7 +770,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
It will also override any fixture-function defined scope, allowing It will also override any fixture-function defined scope, allowing
to set a dynamic scope using test context or configuration. to set a dynamic scope using test context or configuration.
""" """
from _pytest.fixtures import scopes from _pytest.fixtures import scope2index
from _pytest.mark import extract_argvalue from _pytest.mark import extract_argvalue
from py.io import saferepr from py.io import saferepr
@ -799,7 +799,8 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
if scope is None: if scope is None:
scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect) scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
scopenum = scopes.index(scope) scopenum = scope2index(
scope, descr='call to {0}'.format(self.parametrize))
valtypes = {} valtypes = {}
for arg in argnames: for arg in argnames:
if arg not in self.fixturenames: if arg not in self.fixturenames:

View File

@ -1063,6 +1063,22 @@ class TestFixtureUsages:
"*1 error*" "*1 error*"
]) ])
def test_invalid_scope(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture(scope="functions")
def badscope():
pass
def test_nothing(badscope):
pass
""")
result = testdir.runpytest_inprocess()
result.stdout.fnmatch_lines(
("*ValueError: fixture badscope from test_invalid_scope.py has an unsupported"
" scope value 'functions'")
)
def test_funcarg_parametrized_and_used_twice(self, testdir): def test_funcarg_parametrized_and_used_twice(self, testdir):
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest

View File

@ -96,6 +96,14 @@ class TestMetafunc:
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
def test_parametrize_bad_scope(self, testdir):
def func(x): pass
metafunc = self.Metafunc(func)
try:
metafunc.parametrize("x", [1], scope='doggy')
except ValueError as ve:
assert "has an unsupported scope value 'doggy'" in str(ve)
def test_parametrize_and_id(self): def test_parametrize_and_id(self):
def func(x, y): pass def func(x, y): pass
metafunc = self.Metafunc(func) metafunc = self.Metafunc(func)