diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 000000000..112d642aa
Binary files /dev/null and b/src/.DS_Store differ
diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py
index a6503bf1d..b32a31874 100644
--- a/src/_pytest/mark/structures.py
+++ b/src/_pytest/mark/structures.py
@@ -162,25 +162,24 @@ class ParameterSet(NamedTuple):
del argvalues
if parameters:
+
# Check all parameter sets have the correct number of values.
for param in parameters:
if len(param.values) != len(argnames):
+ # Construct a string representation of the expected parameter names
+ expected_argnames = ', '.join(argnames)
+ # Construct a string representation of the provided parameter values
+ provided_values = ', '.join(map(repr, param.values))
msg = (
- '{nodeid}: in "parametrize" the number of names ({names_len}):\n'
- " {names}\n"
- "must be equal to the number of values ({values_len}):\n"
- " {values}"
- )
- fail(
- msg.format(
- nodeid=nodeid,
- values=param.values,
- names=argnames,
- names_len=len(argnames),
- values_len=len(param.values),
- ),
- pytrace=False,
+ f'{nodeid}: \n\n Error in parameterization for test "{func.__name__}".\n '
+ f'The number of specified parameters ({len(argnames)}) '
+ f'does not match the number of provided values ({len(param.values)}): {provided_values}. \n'
+ f' Please ensure that the correct number of parameter names '
+ f'({len(param.values)}) are separated by commas within quotes.\n\n'
+ f'Require more than parameter names: \"{expected_argnames}\"'
)
+
+ fail(msg, pytrace=False)
else:
# Empty parameter set (likely computed at runtime): create a single
# parameter set with NOTSET values, with the "empty parameter set" mark applied to it.
diff --git a/src/_pytest/python.py b/src/_pytest/python.py
index 5e059f2c4..18bb9057c 100644
--- a/src/_pytest/python.py
+++ b/src/_pytest/python.py
@@ -1371,11 +1371,19 @@ class Metafunc:
# num_ids == 0 is a special case: https://github.com/pytest-dev/pytest/issues/1849
if num_ids != len(parametersets) and num_ids != 0:
- msg = "In {}: {} parameter sets specified, with different number of ids: {}"
- fail(msg.format(func_name, len(parametersets), num_ids), pytrace=False)
+ # Construct a string representation of the expected parameter sets
+ expected_paramsets = len(parametersets)
+
+ msg = (
+ f"In {func_name}: \n\n"
+ f" Specified {expected_paramsets} parameter sets with {num_ids} different ids. \n"
+ f" Ensure all subparameters are correctly grouped within a single set of quotation marks."
+ )
+ fail(msg, pytrace=False)
return list(itertools.islice(ids, num_ids))
+
def _resolve_args_directness(
self,
argnames: Sequence[str],
@@ -1402,8 +1410,24 @@ class Metafunc:
arg_directness = dict.fromkeys(argnames, "direct")
for arg in indirect:
if arg not in argnames:
+ # Construct a list of valid parameter names
+ valid_params = ', '.join([f'"{name}"' for name in argnames])
+
+ # Construct a string representing the expected number of parameters
+ expected_param_count = len(indirect[0])
+
+ # Construct a string representing the actual number of parameters provided
+ actual_param_count = len(argnames)
+
+
fail(
- f"In {self.function.__name__}: indirect fixture '{arg}' doesn't exist",
+ f"In function {self.function.__name__}: {argnames} is not a valid parameter. "
+ f"Expected {expected_param_count} sub parameters, but only {actual_param_count} were provided. \n\n"
+ f"Make sure to pass parameter names as strings without quotes, separated by commas, \n "
+ f"e.g., '@pytest.mark.parametrize({valid_params}, )'"
+ f"\n\n"
+ f"Or if multiple parameters are used, separate them by commas. \n "
+ f"e.g., '@pytest.mark.parametrize(\"arg1, arg2\", )'",
pytrace=False,
)
arg_directness[arg] = "indirect"
@@ -1415,6 +1439,9 @@ class Metafunc:
)
return arg_directness
+
+
+
def _validate_if_using_arg_names(
self,
argnames: Sequence[str],