Explain a bad scope value to the user
This commit is contained in:
parent
7660a19d0a
commit
6db2f315fa
1
AUTHORS
1
AUTHORS
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue