Merge pull request #3367 from brianmaissy/feature/indicative_error_for_parametrize_with_default_argument
added indicative error when parametrizing an argument with a default …
This commit is contained in:
commit
2a480c59ae
|
@ -135,6 +135,14 @@ def getfuncargnames(function, is_method=False, cls=None):
|
||||||
return arg_names
|
return arg_names
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_arg_names(function):
|
||||||
|
# Note: this code intentionally mirrors the code at the beginning of getfuncargnames,
|
||||||
|
# to get the arguments which were excluded from its result because they had default values
|
||||||
|
return tuple(p.name for p in signature(function).parameters.values()
|
||||||
|
if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) and
|
||||||
|
p.default is not Parameter.empty)
|
||||||
|
|
||||||
|
|
||||||
if _PY3:
|
if _PY3:
|
||||||
STRING_TYPES = bytes, str
|
STRING_TYPES = bytes, str
|
||||||
UNICODE_TYPES = str,
|
UNICODE_TYPES = str,
|
||||||
|
|
|
@ -25,7 +25,7 @@ from _pytest.compat import (
|
||||||
isclass, isfunction, is_generator, ascii_escaped,
|
isclass, isfunction, is_generator, ascii_escaped,
|
||||||
REGEX_TYPE, STRING_TYPES, NoneType, NOTSET,
|
REGEX_TYPE, STRING_TYPES, NoneType, NOTSET,
|
||||||
get_real_func, getfslineno, safe_getattr,
|
get_real_func, getfslineno, safe_getattr,
|
||||||
safe_str, getlocation, enum,
|
safe_str, getlocation, enum, get_default_arg_names
|
||||||
)
|
)
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
from _pytest.mark.structures import transfer_markers
|
from _pytest.mark.structures import transfer_markers
|
||||||
|
@ -790,6 +790,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
||||||
argnames, parameters = ParameterSet._for_parametrize(
|
argnames, parameters = ParameterSet._for_parametrize(
|
||||||
argnames, argvalues, self.function, self.config)
|
argnames, argvalues, self.function, self.config)
|
||||||
del argvalues
|
del argvalues
|
||||||
|
default_arg_names = set(get_default_arg_names(self.function))
|
||||||
|
|
||||||
if scope is None:
|
if scope is None:
|
||||||
scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
|
scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
|
||||||
|
@ -798,13 +799,16 @@ class Metafunc(fixtures.FuncargnamesCompatAttr):
|
||||||
valtypes = {}
|
valtypes = {}
|
||||||
for arg in argnames:
|
for arg in argnames:
|
||||||
if arg not in self.fixturenames:
|
if arg not in self.fixturenames:
|
||||||
if isinstance(indirect, (tuple, list)):
|
if arg in default_arg_names:
|
||||||
name = 'fixture' if arg in indirect else 'argument'
|
raise ValueError("%r already takes an argument %r with a default value" % (self.function, arg))
|
||||||
else:
|
else:
|
||||||
name = 'fixture' if indirect else 'argument'
|
if isinstance(indirect, (tuple, list)):
|
||||||
raise ValueError(
|
name = 'fixture' if arg in indirect else 'argument'
|
||||||
"%r uses no %s %r" % (
|
else:
|
||||||
self.function, name, arg))
|
name = 'fixture' if indirect else 'argument'
|
||||||
|
raise ValueError(
|
||||||
|
"%r uses no %s %r" % (
|
||||||
|
self.function, name, arg))
|
||||||
|
|
||||||
if indirect is True:
|
if indirect is True:
|
||||||
valtypes = dict.fromkeys(argnames, "params")
|
valtypes = dict.fromkeys(argnames, "params")
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Added a more indicative error message when parametrizing a function whose argument takes a default value.
|
|
@ -616,6 +616,19 @@ class TestMetafunc(object):
|
||||||
"*uses no argument 'y'*",
|
"*uses no argument 'y'*",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_parametrize_gives_indicative_error_on_function_with_default_argument(self, testdir):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('x, y', [('a', 'b')])
|
||||||
|
def test_simple(x, y=1):
|
||||||
|
assert len(x) == 1
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest("--collect-only")
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*already takes an argument 'y' with a default value",
|
||||||
|
])
|
||||||
|
|
||||||
def test_addcalls_and_parametrize_indirect(self):
|
def test_addcalls_and_parametrize_indirect(self):
|
||||||
def func(x, y):
|
def func(x, y):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in New Issue