Merge pull request #6735 from bluetech/metafunc-annotate
Type annotate Metafunc
This commit is contained in:
		
						commit
						7b8968ff80
					
				| 
						 | 
				
			
			@ -227,7 +227,7 @@ def _bytes_to_ascii(val: bytes) -> str:
 | 
			
		|||
    return val.decode("ascii", "backslashreplace")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def ascii_escaped(val: Union[bytes, str]):
 | 
			
		||||
def ascii_escaped(val: Union[bytes, str]) -> str:
 | 
			
		||||
    """If val is pure ascii, returns it as a str().  Otherwise, escapes
 | 
			
		||||
    bytes objects into a sequence of escaped bytes:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,14 +2,18 @@
 | 
			
		|||
import enum
 | 
			
		||||
import fnmatch
 | 
			
		||||
import inspect
 | 
			
		||||
import itertools
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import typing
 | 
			
		||||
import warnings
 | 
			
		||||
from collections import Counter
 | 
			
		||||
from collections import defaultdict
 | 
			
		||||
from collections.abc import Sequence
 | 
			
		||||
from functools import partial
 | 
			
		||||
from typing import Callable
 | 
			
		||||
from typing import Dict
 | 
			
		||||
from typing import Iterable
 | 
			
		||||
from typing import List
 | 
			
		||||
from typing import Optional
 | 
			
		||||
from typing import Tuple
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +27,8 @@ from _pytest import nodes
 | 
			
		|||
from _pytest._code import filter_traceback
 | 
			
		||||
from _pytest._code.code import ExceptionInfo
 | 
			
		||||
from _pytest._code.source import getfslineno
 | 
			
		||||
from _pytest._io import TerminalWriter
 | 
			
		||||
from _pytest._io.saferepr import saferepr
 | 
			
		||||
from _pytest.compat import ascii_escaped
 | 
			
		||||
from _pytest.compat import get_default_arg_names
 | 
			
		||||
from _pytest.compat import get_real_func
 | 
			
		||||
| 
						 | 
				
			
			@ -35,8 +41,10 @@ from _pytest.compat import REGEX_TYPE
 | 
			
		|||
from _pytest.compat import safe_getattr
 | 
			
		||||
from _pytest.compat import safe_isclass
 | 
			
		||||
from _pytest.compat import STRING_TYPES
 | 
			
		||||
from _pytest.config import Config
 | 
			
		||||
from _pytest.config import hookimpl
 | 
			
		||||
from _pytest.deprecated import FUNCARGNAMES
 | 
			
		||||
from _pytest.fixtures import FuncFixtureInfo
 | 
			
		||||
from _pytest.mark import MARK_GEN
 | 
			
		||||
from _pytest.mark import ParameterSet
 | 
			
		||||
from _pytest.mark.structures import get_unpacked_marks
 | 
			
		||||
| 
						 | 
				
			
			@ -125,9 +133,10 @@ def pytest_cmdline_main(config):
 | 
			
		|||
        return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def pytest_generate_tests(metafunc):
 | 
			
		||||
def pytest_generate_tests(metafunc: "Metafunc") -> None:
 | 
			
		||||
    for marker in metafunc.definition.iter_markers(name="parametrize"):
 | 
			
		||||
        metafunc.parametrize(*marker.args, **marker.kwargs, _param_mark=marker)
 | 
			
		||||
        # TODO: Fix this type-ignore (overlapping kwargs).
 | 
			
		||||
        metafunc.parametrize(*marker.args, **marker.kwargs, _param_mark=marker)  # type: ignore[misc] # noqa: F821
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def pytest_configure(config):
 | 
			
		||||
| 
						 | 
				
			
			@ -839,8 +848,8 @@ class Metafunc:
 | 
			
		|||
    def __init__(
 | 
			
		||||
        self,
 | 
			
		||||
        definition: "FunctionDefinition",
 | 
			
		||||
        fixtureinfo,
 | 
			
		||||
        config,
 | 
			
		||||
        fixtureinfo: fixtures.FuncFixtureInfo,
 | 
			
		||||
        config: Config,
 | 
			
		||||
        cls=None,
 | 
			
		||||
        module=None,
 | 
			
		||||
    ) -> None:
 | 
			
		||||
| 
						 | 
				
			
			@ -872,14 +881,19 @@ class Metafunc:
 | 
			
		|||
 | 
			
		||||
    def parametrize(
 | 
			
		||||
        self,
 | 
			
		||||
        argnames,
 | 
			
		||||
        argvalues,
 | 
			
		||||
        indirect=False,
 | 
			
		||||
        ids=None,
 | 
			
		||||
        scope=None,
 | 
			
		||||
        argnames: Union[str, List[str], Tuple[str, ...]],
 | 
			
		||||
        argvalues: Iterable[Union[ParameterSet, typing.Sequence[object], object]],
 | 
			
		||||
        indirect: Union[bool, typing.Sequence[str]] = False,
 | 
			
		||||
        ids: Optional[
 | 
			
		||||
            Union[
 | 
			
		||||
                Iterable[Union[None, str, float, int, bool]],
 | 
			
		||||
                Callable[[object], Optional[object]],
 | 
			
		||||
            ]
 | 
			
		||||
        ] = None,
 | 
			
		||||
        scope: "Optional[str]" = None,
 | 
			
		||||
        *,
 | 
			
		||||
        _param_mark: Optional[Mark] = None
 | 
			
		||||
    ):
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """ Add new invocations to the underlying test function using the list
 | 
			
		||||
        of argvalues for the given argnames.  Parametrization is performed
 | 
			
		||||
        during the collection phase.  If you need to setup expensive resources
 | 
			
		||||
| 
						 | 
				
			
			@ -988,8 +1002,17 @@ class Metafunc:
 | 
			
		|||
        self._calls = newcalls
 | 
			
		||||
 | 
			
		||||
    def _resolve_arg_ids(
 | 
			
		||||
        self, argnames: List[str], ids, parameters: List[ParameterSet], item: nodes.Item
 | 
			
		||||
    ):
 | 
			
		||||
        self,
 | 
			
		||||
        argnames: typing.Sequence[str],
 | 
			
		||||
        ids: Optional[
 | 
			
		||||
            Union[
 | 
			
		||||
                Iterable[Union[None, str, float, int, bool]],
 | 
			
		||||
                Callable[[object], Optional[object]],
 | 
			
		||||
            ]
 | 
			
		||||
        ],
 | 
			
		||||
        parameters: typing.Sequence[ParameterSet],
 | 
			
		||||
        item,
 | 
			
		||||
    ) -> List[str]:
 | 
			
		||||
        """Resolves the actual ids for the given argnames, based on the ``ids`` parameter given
 | 
			
		||||
        to ``parametrize``.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1000,41 +1023,44 @@ class Metafunc:
 | 
			
		|||
        :rtype: List[str]
 | 
			
		||||
        :return: the list of ids for each argname given
 | 
			
		||||
        """
 | 
			
		||||
        if ids is None:
 | 
			
		||||
            idfn = None
 | 
			
		||||
        if callable(ids):
 | 
			
		||||
            ids_ = None
 | 
			
		||||
        elif callable(ids):
 | 
			
		||||
            idfn = ids
 | 
			
		||||
            ids = None
 | 
			
		||||
        if ids:
 | 
			
		||||
            func_name = self.function.__name__
 | 
			
		||||
            ids = self._validate_ids(ids, parameters, func_name)
 | 
			
		||||
        ids = idmaker(argnames, parameters, idfn, ids, self.config, item=item)
 | 
			
		||||
        return ids
 | 
			
		||||
            ids_ = None
 | 
			
		||||
        else:
 | 
			
		||||
            idfn = None
 | 
			
		||||
            ids_ = self._validate_ids(ids, parameters, self.function.__name__)
 | 
			
		||||
        return idmaker(argnames, parameters, idfn, ids_, self.config, item=item)
 | 
			
		||||
 | 
			
		||||
    def _validate_ids(self, ids, parameters, func_name):
 | 
			
		||||
    def _validate_ids(
 | 
			
		||||
        self,
 | 
			
		||||
        ids: Iterable[Union[None, str, float, int, bool]],
 | 
			
		||||
        parameters: typing.Sequence[ParameterSet],
 | 
			
		||||
        func_name: str,
 | 
			
		||||
    ) -> List[Union[None, str]]:
 | 
			
		||||
        try:
 | 
			
		||||
            len(ids)
 | 
			
		||||
            num_ids = len(ids)  # type: ignore[arg-type] # noqa: F821
 | 
			
		||||
        except TypeError:
 | 
			
		||||
            try:
 | 
			
		||||
                it = iter(ids)
 | 
			
		||||
                iter(ids)
 | 
			
		||||
            except TypeError:
 | 
			
		||||
                raise TypeError("ids must be a callable, sequence or generator")
 | 
			
		||||
            else:
 | 
			
		||||
                import itertools
 | 
			
		||||
                raise TypeError("ids must be a callable or an iterable")
 | 
			
		||||
            num_ids = len(parameters)
 | 
			
		||||
 | 
			
		||||
                new_ids = list(itertools.islice(it, len(parameters)))
 | 
			
		||||
        else:
 | 
			
		||||
            new_ids = list(ids)
 | 
			
		||||
 | 
			
		||||
        if len(new_ids) != len(parameters):
 | 
			
		||||
        # num_ids == 0 is a special case: https://github.com/pytest-dev/pytest/issues/1849
 | 
			
		||||
        if num_ids != len(parameters) and num_ids != 0:
 | 
			
		||||
            msg = "In {}: {} parameter sets specified, with different number of ids: {}"
 | 
			
		||||
            fail(msg.format(func_name, len(parameters), len(ids)), pytrace=False)
 | 
			
		||||
        for idx, id_value in enumerate(new_ids):
 | 
			
		||||
            if id_value is not None:
 | 
			
		||||
                if isinstance(id_value, (float, int, bool)):
 | 
			
		||||
                    new_ids[idx] = str(id_value)
 | 
			
		||||
                elif not isinstance(id_value, str):
 | 
			
		||||
                    from _pytest._io.saferepr import saferepr
 | 
			
		||||
            fail(msg.format(func_name, len(parameters), num_ids), pytrace=False)
 | 
			
		||||
 | 
			
		||||
        new_ids = []
 | 
			
		||||
        for idx, id_value in enumerate(itertools.islice(ids, num_ids)):
 | 
			
		||||
            if id_value is None or isinstance(id_value, str):
 | 
			
		||||
                new_ids.append(id_value)
 | 
			
		||||
            elif isinstance(id_value, (float, int, bool)):
 | 
			
		||||
                new_ids.append(str(id_value))
 | 
			
		||||
            else:
 | 
			
		||||
                msg = "In {}: ids must be list of string/float/int/bool, found: {} (type: {!r}) at index {}"
 | 
			
		||||
                fail(
 | 
			
		||||
                    msg.format(func_name, saferepr(id_value), type(id_value), idx),
 | 
			
		||||
| 
						 | 
				
			
			@ -1042,7 +1068,11 @@ class Metafunc:
 | 
			
		|||
                )
 | 
			
		||||
        return new_ids
 | 
			
		||||
 | 
			
		||||
    def _resolve_arg_value_types(self, argnames: List[str], indirect) -> Dict[str, str]:
 | 
			
		||||
    def _resolve_arg_value_types(
 | 
			
		||||
        self,
 | 
			
		||||
        argnames: typing.Sequence[str],
 | 
			
		||||
        indirect: Union[bool, typing.Sequence[str]],
 | 
			
		||||
    ) -> Dict[str, str]:
 | 
			
		||||
        """Resolves if each parametrized argument must be considered a parameter to a fixture or a "funcarg"
 | 
			
		||||
        to the function, based on the ``indirect`` parameter of the parametrized() call.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1075,7 +1105,11 @@ class Metafunc:
 | 
			
		|||
            )
 | 
			
		||||
        return valtypes
 | 
			
		||||
 | 
			
		||||
    def _validate_if_using_arg_names(self, argnames, indirect):
 | 
			
		||||
    def _validate_if_using_arg_names(
 | 
			
		||||
        self,
 | 
			
		||||
        argnames: typing.Sequence[str],
 | 
			
		||||
        indirect: Union[bool, typing.Sequence[str]],
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Check if all argnames are being used, by default values, or directly/indirectly.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1095,7 +1129,7 @@ class Metafunc:
 | 
			
		|||
                        pytrace=False,
 | 
			
		||||
                    )
 | 
			
		||||
                else:
 | 
			
		||||
                    if isinstance(indirect, (tuple, list)):
 | 
			
		||||
                    if isinstance(indirect, Sequence):
 | 
			
		||||
                        name = "fixture" if arg in indirect else "argument"
 | 
			
		||||
                    else:
 | 
			
		||||
                        name = "fixture" if indirect else "argument"
 | 
			
		||||
| 
						 | 
				
			
			@ -1104,7 +1138,11 @@ class Metafunc:
 | 
			
		|||
                        pytrace=False,
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
    def _validate_explicit_parameters(self, argnames, indirect):
 | 
			
		||||
    def _validate_explicit_parameters(
 | 
			
		||||
        self,
 | 
			
		||||
        argnames: typing.Sequence[str],
 | 
			
		||||
        indirect: Union[bool, typing.Sequence[str]],
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        The argnames in *parametrize* should either be declared explicitly via
 | 
			
		||||
        indirect list or in the function signature
 | 
			
		||||
| 
						 | 
				
			
			@ -1113,17 +1151,15 @@ class Metafunc:
 | 
			
		|||
        :param indirect: same ``indirect`` parameter of ``parametrize()``.
 | 
			
		||||
        :raise ValueError: if validation fails
 | 
			
		||||
        """
 | 
			
		||||
        if isinstance(indirect, bool) and indirect is True:
 | 
			
		||||
            return
 | 
			
		||||
        parametrized_argnames = list()
 | 
			
		||||
        funcargnames = _pytest.compat.getfuncargnames(self.function)
 | 
			
		||||
        if isinstance(indirect, Sequence):
 | 
			
		||||
            for arg in argnames:
 | 
			
		||||
                if arg not in indirect:
 | 
			
		||||
                    parametrized_argnames.append(arg)
 | 
			
		||||
        elif indirect is False:
 | 
			
		||||
            parametrized_argnames = argnames
 | 
			
		||||
        if isinstance(indirect, bool):
 | 
			
		||||
            parametrized_argnames = [] if indirect else argnames
 | 
			
		||||
        else:
 | 
			
		||||
            parametrized_argnames = [arg for arg in argnames if arg not in indirect]
 | 
			
		||||
 | 
			
		||||
        if not parametrized_argnames:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        funcargnames = _pytest.compat.getfuncargnames(self.function)
 | 
			
		||||
        usefixtures = fixtures.get_use_fixtures_for_node(self.definition)
 | 
			
		||||
 | 
			
		||||
        for arg in parametrized_argnames:
 | 
			
		||||
| 
						 | 
				
			
			@ -1169,17 +1205,27 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
 | 
			
		|||
    return "function"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _ascii_escaped_by_config(val, config):
 | 
			
		||||
def _ascii_escaped_by_config(val: Union[str, bytes], config: Optional[Config]) -> str:
 | 
			
		||||
    if config is None:
 | 
			
		||||
        escape_option = False
 | 
			
		||||
    else:
 | 
			
		||||
        escape_option = config.getini(
 | 
			
		||||
            "disable_test_id_escaping_and_forfeit_all_rights_to_community_support"
 | 
			
		||||
        )
 | 
			
		||||
    return val if escape_option else ascii_escaped(val)
 | 
			
		||||
    # TODO: If escaping is turned off and the user passes bytes,
 | 
			
		||||
    #       will return a bytes. For now we ignore this but the
 | 
			
		||||
    #       code *probably* doesn't handle this case.
 | 
			
		||||
    return val if escape_option else ascii_escaped(val)  # type: ignore
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _idval(val, argname, idx, idfn, item, config):
 | 
			
		||||
def _idval(
 | 
			
		||||
    val: object,
 | 
			
		||||
    argname: str,
 | 
			
		||||
    idx: int,
 | 
			
		||||
    idfn: Optional[Callable[[object], Optional[object]]],
 | 
			
		||||
    item,
 | 
			
		||||
    config: Optional[Config],
 | 
			
		||||
) -> str:
 | 
			
		||||
    if idfn:
 | 
			
		||||
        try:
 | 
			
		||||
            generated_id = idfn(val)
 | 
			
		||||
| 
						 | 
				
			
			@ -1192,7 +1238,7 @@ def _idval(val, argname, idx, idfn, item, config):
 | 
			
		|||
    elif config:
 | 
			
		||||
        hook_id = config.hook.pytest_make_parametrize_id(
 | 
			
		||||
            config=config, val=val, argname=argname
 | 
			
		||||
        )
 | 
			
		||||
        )  # type: Optional[str]
 | 
			
		||||
        if hook_id:
 | 
			
		||||
            return hook_id
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1204,48 +1250,65 @@ def _idval(val, argname, idx, idfn, item, config):
 | 
			
		|||
        return ascii_escaped(val.pattern)
 | 
			
		||||
    elif isinstance(val, enum.Enum):
 | 
			
		||||
        return str(val)
 | 
			
		||||
    elif hasattr(val, "__name__") and isinstance(val.__name__, str):
 | 
			
		||||
    elif isinstance(getattr(val, "__name__", None), str):
 | 
			
		||||
        # name of a class, function, module, etc.
 | 
			
		||||
        return val.__name__
 | 
			
		||||
        name = getattr(val, "__name__")  # type: str
 | 
			
		||||
        return name
 | 
			
		||||
    return str(argname) + str(idx)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _idvalset(idx, parameterset, argnames, idfn, ids, item, config):
 | 
			
		||||
def _idvalset(
 | 
			
		||||
    idx: int,
 | 
			
		||||
    parameterset: ParameterSet,
 | 
			
		||||
    argnames: Iterable[str],
 | 
			
		||||
    idfn: Optional[Callable[[object], Optional[object]]],
 | 
			
		||||
    ids: Optional[List[Union[None, str]]],
 | 
			
		||||
    item,
 | 
			
		||||
    config: Optional[Config],
 | 
			
		||||
):
 | 
			
		||||
    if parameterset.id is not None:
 | 
			
		||||
        return parameterset.id
 | 
			
		||||
    if ids is None or (idx >= len(ids) or ids[idx] is None):
 | 
			
		||||
    id = None if ids is None or idx >= len(ids) else ids[idx]
 | 
			
		||||
    if id is None:
 | 
			
		||||
        this_id = [
 | 
			
		||||
            _idval(val, argname, idx, idfn, item=item, config=config)
 | 
			
		||||
            for val, argname in zip(parameterset.values, argnames)
 | 
			
		||||
        ]
 | 
			
		||||
        return "-".join(this_id)
 | 
			
		||||
    else:
 | 
			
		||||
        return _ascii_escaped_by_config(ids[idx], config)
 | 
			
		||||
        return _ascii_escaped_by_config(id, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def idmaker(argnames, parametersets, idfn=None, ids=None, config=None, item=None):
 | 
			
		||||
    ids = [
 | 
			
		||||
def idmaker(
 | 
			
		||||
    argnames: Iterable[str],
 | 
			
		||||
    parametersets: Iterable[ParameterSet],
 | 
			
		||||
    idfn: Optional[Callable[[object], Optional[object]]] = None,
 | 
			
		||||
    ids: Optional[List[Union[None, str]]] = None,
 | 
			
		||||
    config: Optional[Config] = None,
 | 
			
		||||
    item=None,
 | 
			
		||||
) -> List[str]:
 | 
			
		||||
    resolved_ids = [
 | 
			
		||||
        _idvalset(valindex, parameterset, argnames, idfn, ids, config=config, item=item)
 | 
			
		||||
        for valindex, parameterset in enumerate(parametersets)
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    # All IDs must be unique!
 | 
			
		||||
    unique_ids = set(ids)
 | 
			
		||||
    if len(unique_ids) != len(ids):
 | 
			
		||||
    unique_ids = set(resolved_ids)
 | 
			
		||||
    if len(unique_ids) != len(resolved_ids):
 | 
			
		||||
 | 
			
		||||
        # Record the number of occurrences of each test ID
 | 
			
		||||
        test_id_counts = Counter(ids)
 | 
			
		||||
        test_id_counts = Counter(resolved_ids)
 | 
			
		||||
 | 
			
		||||
        # Map the test ID to its next suffix
 | 
			
		||||
        test_id_suffixes = defaultdict(int)
 | 
			
		||||
        test_id_suffixes = defaultdict(int)  # type: Dict[str, int]
 | 
			
		||||
 | 
			
		||||
        # Suffix non-unique IDs to make them unique
 | 
			
		||||
        for index, test_id in enumerate(ids):
 | 
			
		||||
        for index, test_id in enumerate(resolved_ids):
 | 
			
		||||
            if test_id_counts[test_id] > 1:
 | 
			
		||||
                ids[index] = "{}{}".format(test_id, test_id_suffixes[test_id])
 | 
			
		||||
                resolved_ids[index] = "{}{}".format(test_id, test_id_suffixes[test_id])
 | 
			
		||||
                test_id_suffixes[test_id] += 1
 | 
			
		||||
 | 
			
		||||
    return ids
 | 
			
		||||
    return resolved_ids
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def show_fixtures_per_test(config):
 | 
			
		||||
| 
						 | 
				
			
			@ -1369,7 +1432,7 @@ def _showfixtures_main(config, session):
 | 
			
		|||
        tw.line()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def write_docstring(tw, doc, indent="    "):
 | 
			
		||||
def write_docstring(tw: TerminalWriter, doc: str, indent: str = "    ") -> None:
 | 
			
		||||
    for line in doc.split("\n"):
 | 
			
		||||
        tw.write(indent + line + "\n")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1388,13 +1451,13 @@ class Function(PyobjMixin, nodes.Item):
 | 
			
		|||
        parent,
 | 
			
		||||
        args=None,
 | 
			
		||||
        config=None,
 | 
			
		||||
        callspec=None,
 | 
			
		||||
        callspec: Optional[CallSpec2] = None,
 | 
			
		||||
        callobj=NOTSET,
 | 
			
		||||
        keywords=None,
 | 
			
		||||
        session=None,
 | 
			
		||||
        fixtureinfo=None,
 | 
			
		||||
        fixtureinfo: Optional[FuncFixtureInfo] = None,
 | 
			
		||||
        originalname=None,
 | 
			
		||||
    ):
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        super().__init__(name, parent, config=config, session=session)
 | 
			
		||||
        self._args = args
 | 
			
		||||
        if callobj is not NOTSET:
 | 
			
		||||
| 
						 | 
				
			
			@ -1430,7 +1493,7 @@ class Function(PyobjMixin, nodes.Item):
 | 
			
		|||
            fixtureinfo = self.session._fixturemanager.getfixtureinfo(
 | 
			
		||||
                self, self.obj, self.cls, funcargs=True
 | 
			
		||||
            )
 | 
			
		||||
        self._fixtureinfo = fixtureinfo
 | 
			
		||||
        self._fixtureinfo = fixtureinfo  # type: FuncFixtureInfo
 | 
			
		||||
        self.fixturenames = fixtureinfo.names_closure
 | 
			
		||||
        self._initrequest()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,13 @@
 | 
			
		|||
import itertools
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
import textwrap
 | 
			
		||||
from typing import Any
 | 
			
		||||
from typing import Iterator
 | 
			
		||||
from typing import List
 | 
			
		||||
from typing import Optional
 | 
			
		||||
from typing import Tuple
 | 
			
		||||
from typing import Union
 | 
			
		||||
 | 
			
		||||
import attr
 | 
			
		||||
import hypothesis
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +16,8 @@ from hypothesis import strategies
 | 
			
		|||
import pytest
 | 
			
		||||
from _pytest import fixtures
 | 
			
		||||
from _pytest import python
 | 
			
		||||
from _pytest.outcomes import fail
 | 
			
		||||
from _pytest.outcomes import Failed
 | 
			
		||||
from _pytest.pytester import Testdir
 | 
			
		||||
from _pytest.python import _idval
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +26,7 @@ class TestMetafunc:
 | 
			
		|||
        # the unit tests of this class check if things work correctly
 | 
			
		||||
        # on the funcarg level, so we don't need a full blown
 | 
			
		||||
        # initialization
 | 
			
		||||
        class FixtureInfo:
 | 
			
		||||
        class FuncFixtureInfoMock:
 | 
			
		||||
            name2fixturedefs = None
 | 
			
		||||
 | 
			
		||||
            def __init__(self, names):
 | 
			
		||||
| 
						 | 
				
			
			@ -32,11 +40,11 @@ class TestMetafunc:
 | 
			
		|||
                return []
 | 
			
		||||
 | 
			
		||||
        names = fixtures.getfuncargnames(func)
 | 
			
		||||
        fixtureinfo = FixtureInfo(names)
 | 
			
		||||
        definition = DefinitionMock._create(func)
 | 
			
		||||
        fixtureinfo = FuncFixtureInfoMock(names)  # type: Any
 | 
			
		||||
        definition = DefinitionMock._create(func)  # type: Any
 | 
			
		||||
        return python.Metafunc(definition, fixtureinfo, config)
 | 
			
		||||
 | 
			
		||||
    def test_no_funcargs(self):
 | 
			
		||||
    def test_no_funcargs(self) -> None:
 | 
			
		||||
        def function():
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +52,7 @@ class TestMetafunc:
 | 
			
		|||
        assert not metafunc.fixturenames
 | 
			
		||||
        repr(metafunc._calls)
 | 
			
		||||
 | 
			
		||||
    def test_function_basic(self):
 | 
			
		||||
    def test_function_basic(self) -> None:
 | 
			
		||||
        def func(arg1, arg2="qwe"):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +62,7 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc.function is func
 | 
			
		||||
        assert metafunc.cls is None
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_error(self):
 | 
			
		||||
    def test_parametrize_error(self) -> None:
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,12 +74,10 @@ class TestMetafunc:
 | 
			
		|||
        pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
 | 
			
		||||
        pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
 | 
			
		||||
 | 
			
		||||
        with pytest.raises(
 | 
			
		||||
            TypeError, match="^ids must be a callable, sequence or generator$"
 | 
			
		||||
        ):
 | 
			
		||||
            metafunc.parametrize("y", [5, 6], ids=42)
 | 
			
		||||
        with pytest.raises(TypeError, match="^ids must be a callable or an iterable$"):
 | 
			
		||||
            metafunc.parametrize("y", [5, 6], ids=42)  # type: ignore[arg-type] # noqa: F821
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_error_iterator(self):
 | 
			
		||||
    def test_parametrize_error_iterator(self) -> None:
 | 
			
		||||
        def func(x):
 | 
			
		||||
            raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,38 +85,40 @@ class TestMetafunc:
 | 
			
		|||
            def __repr__(self):
 | 
			
		||||
                return "Exc(from_gen)"
 | 
			
		||||
 | 
			
		||||
        def gen():
 | 
			
		||||
        def gen() -> Iterator[Union[int, None, Exc]]:
 | 
			
		||||
            yield 0
 | 
			
		||||
            yield None
 | 
			
		||||
            yield Exc()
 | 
			
		||||
 | 
			
		||||
        metafunc = self.Metafunc(func)
 | 
			
		||||
        metafunc.parametrize("x", [1, 2], ids=gen())
 | 
			
		||||
        # When the input is an iterator, only len(args) are taken,
 | 
			
		||||
        # so the bad Exc isn't reached.
 | 
			
		||||
        metafunc.parametrize("x", [1, 2], ids=gen())  # type: ignore[arg-type] # noqa: F821
 | 
			
		||||
        assert [(x.funcargs, x.id) for x in metafunc._calls] == [
 | 
			
		||||
            ({"x": 1}, "0"),
 | 
			
		||||
            ({"x": 2}, "2"),
 | 
			
		||||
        ]
 | 
			
		||||
        with pytest.raises(
 | 
			
		||||
            fail.Exception,
 | 
			
		||||
            Failed,
 | 
			
		||||
            match=(
 | 
			
		||||
                r"In func: ids must be list of string/float/int/bool, found:"
 | 
			
		||||
                r" Exc\(from_gen\) \(type: <class .*Exc'>\) at index 2"
 | 
			
		||||
            ),
 | 
			
		||||
        ):
 | 
			
		||||
            metafunc.parametrize("x", [1, 2, 3], ids=gen())
 | 
			
		||||
            metafunc.parametrize("x", [1, 2, 3], ids=gen())  # type: ignore[arg-type] # noqa: F821
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_bad_scope(self):
 | 
			
		||||
    def test_parametrize_bad_scope(self) -> None:
 | 
			
		||||
        def func(x):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        metafunc = self.Metafunc(func)
 | 
			
		||||
        with pytest.raises(
 | 
			
		||||
            pytest.fail.Exception,
 | 
			
		||||
            Failed,
 | 
			
		||||
            match=r"parametrize\(\) call in func got an unexpected scope value 'doggy'",
 | 
			
		||||
        ):
 | 
			
		||||
            metafunc.parametrize("x", [1], scope="doggy")
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_request_name(self, testdir):
 | 
			
		||||
    def test_parametrize_request_name(self, testdir: Testdir) -> None:
 | 
			
		||||
        """Show proper error  when 'request' is used as a parameter name in parametrize (#6183)"""
 | 
			
		||||
 | 
			
		||||
        def func(request):
 | 
			
		||||
| 
						 | 
				
			
			@ -118,12 +126,12 @@ class TestMetafunc:
 | 
			
		|||
 | 
			
		||||
        metafunc = self.Metafunc(func)
 | 
			
		||||
        with pytest.raises(
 | 
			
		||||
            pytest.fail.Exception,
 | 
			
		||||
            Failed,
 | 
			
		||||
            match=r"'request' is a reserved name and cannot be used in @pytest.mark.parametrize",
 | 
			
		||||
        ):
 | 
			
		||||
            metafunc.parametrize("request", [1])
 | 
			
		||||
 | 
			
		||||
    def test_find_parametrized_scope(self):
 | 
			
		||||
    def test_find_parametrized_scope(self) -> None:
 | 
			
		||||
        """unittest for _find_parametrized_scope (#3941)"""
 | 
			
		||||
        from _pytest.python import _find_parametrized_scope
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +177,7 @@ class TestMetafunc:
 | 
			
		|||
            == "module"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_and_id(self):
 | 
			
		||||
    def test_parametrize_and_id(self) -> None:
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +188,7 @@ class TestMetafunc:
 | 
			
		|||
        ids = [x.id for x in metafunc._calls]
 | 
			
		||||
        assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"]
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_and_id_unicode(self):
 | 
			
		||||
    def test_parametrize_and_id_unicode(self) -> None:
 | 
			
		||||
        """Allow unicode strings for "ids" parameter in Python 2 (##1905)"""
 | 
			
		||||
 | 
			
		||||
        def func(x):
 | 
			
		||||
| 
						 | 
				
			
			@ -191,23 +199,21 @@ class TestMetafunc:
 | 
			
		|||
        ids = [x.id for x in metafunc._calls]
 | 
			
		||||
        assert ids == ["basic", "advanced"]
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_with_wrong_number_of_ids(self):
 | 
			
		||||
    def test_parametrize_with_wrong_number_of_ids(self) -> None:
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        metafunc = self.Metafunc(func)
 | 
			
		||||
 | 
			
		||||
        with pytest.raises(pytest.fail.Exception):
 | 
			
		||||
        with pytest.raises(Failed):
 | 
			
		||||
            metafunc.parametrize("x", [1, 2], ids=["basic"])
 | 
			
		||||
 | 
			
		||||
        with pytest.raises(pytest.fail.Exception):
 | 
			
		||||
        with pytest.raises(Failed):
 | 
			
		||||
            metafunc.parametrize(
 | 
			
		||||
                ("x", "y"), [("abc", "def"), ("ghi", "jkl")], ids=["one"]
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_ids_iterator_without_mark(self):
 | 
			
		||||
        import itertools
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_ids_iterator_without_mark(self) -> None:
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +231,7 @@ class TestMetafunc:
 | 
			
		|||
        ids = [x.id for x in metafunc._calls]
 | 
			
		||||
        assert ids == ["4-6", "4-7", "5-6", "5-7"]
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_empty_list(self):
 | 
			
		||||
    def test_parametrize_empty_list(self) -> None:
 | 
			
		||||
        """#510"""
 | 
			
		||||
 | 
			
		||||
        def func(y):
 | 
			
		||||
| 
						 | 
				
			
			@ -246,7 +252,7 @@ class TestMetafunc:
 | 
			
		|||
        metafunc.parametrize("y", [])
 | 
			
		||||
        assert "skip" == metafunc._calls[0].marks[0].name
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_with_userobjects(self):
 | 
			
		||||
    def test_parametrize_with_userobjects(self) -> None:
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -266,12 +272,12 @@ class TestMetafunc:
 | 
			
		|||
    @hypothesis.settings(
 | 
			
		||||
        deadline=400.0
 | 
			
		||||
    )  # very close to std deadline and CI boxes are not reliable in CPU power
 | 
			
		||||
    def test_idval_hypothesis(self, value):
 | 
			
		||||
    def test_idval_hypothesis(self, value) -> None:
 | 
			
		||||
        escaped = _idval(value, "a", 6, None, item=None, config=None)
 | 
			
		||||
        assert isinstance(escaped, str)
 | 
			
		||||
        escaped.encode("ascii")
 | 
			
		||||
 | 
			
		||||
    def test_unicode_idval(self):
 | 
			
		||||
    def test_unicode_idval(self) -> None:
 | 
			
		||||
        """This tests that Unicode strings outside the ASCII character set get
 | 
			
		||||
        escaped, using byte escapes if they're in that range or unicode
 | 
			
		||||
        escapes if they're not.
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +297,7 @@ class TestMetafunc:
 | 
			
		|||
        for val, expected in values:
 | 
			
		||||
            assert _idval(val, "a", 6, None, item=None, config=None) == expected
 | 
			
		||||
 | 
			
		||||
    def test_unicode_idval_with_config(self):
 | 
			
		||||
    def test_unicode_idval_with_config(self) -> None:
 | 
			
		||||
        """unittest for expected behavior to obtain ids with
 | 
			
		||||
        disable_test_id_escaping_and_forfeit_all_rights_to_community_support
 | 
			
		||||
        option. (#5294)
 | 
			
		||||
| 
						 | 
				
			
			@ -316,11 +322,12 @@ class TestMetafunc:
 | 
			
		|||
        values = [
 | 
			
		||||
            ("ação", MockConfig({option: True}), "ação"),
 | 
			
		||||
            ("ação", MockConfig({option: False}), "a\\xe7\\xe3o"),
 | 
			
		||||
        ]
 | 
			
		||||
        ]  # type: List[Tuple[str, Any, str]]
 | 
			
		||||
        for val, config, expected in values:
 | 
			
		||||
            assert _idval(val, "a", 6, None, item=None, config=config) == expected
 | 
			
		||||
            actual = _idval(val, "a", 6, None, item=None, config=config)
 | 
			
		||||
            assert actual == expected
 | 
			
		||||
 | 
			
		||||
    def test_bytes_idval(self):
 | 
			
		||||
    def test_bytes_idval(self) -> None:
 | 
			
		||||
        """unittest for the expected behavior to obtain ids for parametrized
 | 
			
		||||
        bytes values:
 | 
			
		||||
        - python2: non-ascii strings are considered bytes and formatted using
 | 
			
		||||
| 
						 | 
				
			
			@ -336,7 +343,7 @@ class TestMetafunc:
 | 
			
		|||
        for val, expected in values:
 | 
			
		||||
            assert _idval(val, "a", 6, idfn=None, item=None, config=None) == expected
 | 
			
		||||
 | 
			
		||||
    def test_class_or_function_idval(self):
 | 
			
		||||
    def test_class_or_function_idval(self) -> None:
 | 
			
		||||
        """unittest for the expected behavior to obtain ids for parametrized
 | 
			
		||||
        values that are classes or functions: their __name__.
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -351,7 +358,7 @@ class TestMetafunc:
 | 
			
		|||
        for val, expected in values:
 | 
			
		||||
            assert _idval(val, "a", 6, None, item=None, config=None) == expected
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_autoname(self):
 | 
			
		||||
    def test_idmaker_autoname(self) -> None:
 | 
			
		||||
        """#250"""
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -368,13 +375,13 @@ class TestMetafunc:
 | 
			
		|||
        result = idmaker(("a", "b"), [pytest.param({}, b"\xc3\xb4")])
 | 
			
		||||
        assert result == ["a0-\\xc3\\xb4"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_with_bytes_regex(self):
 | 
			
		||||
    def test_idmaker_with_bytes_regex(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        result = idmaker(("a"), [pytest.param(re.compile(b"foo"), 1.0)])
 | 
			
		||||
        assert result == ["foo"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_native_strings(self):
 | 
			
		||||
    def test_idmaker_native_strings(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
| 
						 | 
				
			
			@ -409,7 +416,7 @@ class TestMetafunc:
 | 
			
		|||
            "\\xc3\\xb4-other",
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_non_printable_characters(self):
 | 
			
		||||
    def test_idmaker_non_printable_characters(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
| 
						 | 
				
			
			@ -425,7 +432,7 @@ class TestMetafunc:
 | 
			
		|||
        )
 | 
			
		||||
        assert result == ["\\x00-1", "\\x05-2", "\\x00-3", "\\x05-4", "\\t-5", "\\t-6"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_manual_ids_must_be_printable(self):
 | 
			
		||||
    def test_idmaker_manual_ids_must_be_printable(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
| 
						 | 
				
			
			@ -437,7 +444,7 @@ class TestMetafunc:
 | 
			
		|||
        )
 | 
			
		||||
        assert result == ["hello \\x00", "hello \\x05"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_enum(self):
 | 
			
		||||
    def test_idmaker_enum(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        enum = pytest.importorskip("enum")
 | 
			
		||||
| 
						 | 
				
			
			@ -445,13 +452,14 @@ class TestMetafunc:
 | 
			
		|||
        result = idmaker(("a", "b"), [pytest.param(e.one, e.two)])
 | 
			
		||||
        assert result == ["Foo.one-Foo.two"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_idfn(self):
 | 
			
		||||
    def test_idmaker_idfn(self) -> None:
 | 
			
		||||
        """#351"""
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        def ids(val):
 | 
			
		||||
        def ids(val: object) -> Optional[str]:
 | 
			
		||||
            if isinstance(val, Exception):
 | 
			
		||||
                return repr(val)
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
            ("a", "b"),
 | 
			
		||||
| 
						 | 
				
			
			@ -464,11 +472,11 @@ class TestMetafunc:
 | 
			
		|||
        )
 | 
			
		||||
        assert result == ["10.0-IndexError()", "20-KeyError()", "three-b2"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_idfn_unique_names(self):
 | 
			
		||||
    def test_idmaker_idfn_unique_names(self) -> None:
 | 
			
		||||
        """#351"""
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        def ids(val):
 | 
			
		||||
        def ids(val: object) -> str:
 | 
			
		||||
            return "a"
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
| 
						 | 
				
			
			@ -482,7 +490,7 @@ class TestMetafunc:
 | 
			
		|||
        )
 | 
			
		||||
        assert result == ["a-a0", "a-a1", "a-a2"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_with_idfn_and_config(self):
 | 
			
		||||
    def test_idmaker_with_idfn_and_config(self) -> None:
 | 
			
		||||
        """unittest for expected behavior to create ids with idfn and
 | 
			
		||||
        disable_test_id_escaping_and_forfeit_all_rights_to_community_support
 | 
			
		||||
        option. (#5294)
 | 
			
		||||
| 
						 | 
				
			
			@ -508,14 +516,14 @@ class TestMetafunc:
 | 
			
		|||
        values = [
 | 
			
		||||
            (MockConfig({option: True}), "ação"),
 | 
			
		||||
            (MockConfig({option: False}), "a\\xe7\\xe3o"),
 | 
			
		||||
        ]
 | 
			
		||||
        ]  # type: List[Tuple[Any, str]]
 | 
			
		||||
        for config, expected in values:
 | 
			
		||||
            result = idmaker(
 | 
			
		||||
                ("a",), [pytest.param("string")], idfn=lambda _: "ação", config=config
 | 
			
		||||
                ("a",), [pytest.param("string")], idfn=lambda _: "ação", config=config,
 | 
			
		||||
            )
 | 
			
		||||
            assert result == [expected]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_with_ids_and_config(self):
 | 
			
		||||
    def test_idmaker_with_ids_and_config(self) -> None:
 | 
			
		||||
        """unittest for expected behavior to create ids with ids and
 | 
			
		||||
        disable_test_id_escaping_and_forfeit_all_rights_to_community_support
 | 
			
		||||
        option. (#5294)
 | 
			
		||||
| 
						 | 
				
			
			@ -541,14 +549,14 @@ class TestMetafunc:
 | 
			
		|||
        values = [
 | 
			
		||||
            (MockConfig({option: True}), "ação"),
 | 
			
		||||
            (MockConfig({option: False}), "a\\xe7\\xe3o"),
 | 
			
		||||
        ]
 | 
			
		||||
        ]  # type: List[Tuple[Any, str]]
 | 
			
		||||
        for config, expected in values:
 | 
			
		||||
            result = idmaker(
 | 
			
		||||
                ("a",), [pytest.param("string")], ids=["ação"], config=config
 | 
			
		||||
                ("a",), [pytest.param("string")], ids=["ação"], config=config,
 | 
			
		||||
            )
 | 
			
		||||
            assert result == [expected]
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_ids_exception(self, testdir):
 | 
			
		||||
    def test_parametrize_ids_exception(self, testdir: Testdir) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        :param testdir: the instance of Testdir class, a temporary
 | 
			
		||||
        test directory.
 | 
			
		||||
| 
						 | 
				
			
			@ -573,7 +581,7 @@ class TestMetafunc:
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_ids_returns_non_string(self, testdir):
 | 
			
		||||
    def test_parametrize_ids_returns_non_string(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """\
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -601,7 +609,7 @@ class TestMetafunc:
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_with_ids(self):
 | 
			
		||||
    def test_idmaker_with_ids(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
| 
						 | 
				
			
			@ -609,7 +617,7 @@ class TestMetafunc:
 | 
			
		|||
        )
 | 
			
		||||
        assert result == ["a", "3-4"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_with_paramset_id(self):
 | 
			
		||||
    def test_idmaker_with_paramset_id(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
| 
						 | 
				
			
			@ -619,7 +627,7 @@ class TestMetafunc:
 | 
			
		|||
        )
 | 
			
		||||
        assert result == ["me", "you"]
 | 
			
		||||
 | 
			
		||||
    def test_idmaker_with_ids_unique_names(self):
 | 
			
		||||
    def test_idmaker_with_ids_unique_names(self) -> None:
 | 
			
		||||
        from _pytest.python import idmaker
 | 
			
		||||
 | 
			
		||||
        result = idmaker(
 | 
			
		||||
| 
						 | 
				
			
			@ -627,7 +635,7 @@ class TestMetafunc:
 | 
			
		|||
        )
 | 
			
		||||
        assert result == ["a0", "a1", "b0", "c", "b1"]
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect(self):
 | 
			
		||||
    def test_parametrize_indirect(self) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
| 
						 | 
				
			
			@ -642,7 +650,7 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc._calls[0].params == dict(x=1, y=2)
 | 
			
		||||
        assert metafunc._calls[1].params == dict(x=1, y=3)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_list(self):
 | 
			
		||||
    def test_parametrize_indirect_list(self) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
| 
						 | 
				
			
			@ -653,7 +661,7 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc._calls[0].funcargs == dict(y="b")
 | 
			
		||||
        assert metafunc._calls[0].params == dict(x="a")
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_list_all(self):
 | 
			
		||||
    def test_parametrize_indirect_list_all(self) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
| 
						 | 
				
			
			@ -664,7 +672,7 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc._calls[0].funcargs == {}
 | 
			
		||||
        assert metafunc._calls[0].params == dict(x="a", y="b")
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_list_empty(self):
 | 
			
		||||
    def test_parametrize_indirect_list_empty(self) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
| 
						 | 
				
			
			@ -675,18 +683,18 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc._calls[0].funcargs == dict(x="a", y="b")
 | 
			
		||||
        assert metafunc._calls[0].params == {}
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_wrong_type(self):
 | 
			
		||||
    def test_parametrize_indirect_wrong_type(self) -> None:
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        metafunc = self.Metafunc(func)
 | 
			
		||||
        with pytest.raises(
 | 
			
		||||
            pytest.fail.Exception,
 | 
			
		||||
            Failed,
 | 
			
		||||
            match="In func: expected Sequence or boolean for indirect, got dict",
 | 
			
		||||
        ):
 | 
			
		||||
            metafunc.parametrize("x, y", [("a", "b")], indirect={})
 | 
			
		||||
            metafunc.parametrize("x, y", [("a", "b")], indirect={})  # type: ignore[arg-type] # noqa: F821
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_list_functional(self, testdir):
 | 
			
		||||
    def test_parametrize_indirect_list_functional(self, testdir: Testdir) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        #714
 | 
			
		||||
        Test parametrization with 'indirect' parameter applied on
 | 
			
		||||
| 
						 | 
				
			
			@ -715,17 +723,19 @@ class TestMetafunc:
 | 
			
		|||
        result = testdir.runpytest("-v")
 | 
			
		||||
        result.stdout.fnmatch_lines(["*test_simple*a-b*", "*1 passed*"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_list_error(self):
 | 
			
		||||
    def test_parametrize_indirect_list_error(self) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
 | 
			
		||||
        def func(x, y):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        metafunc = self.Metafunc(func)
 | 
			
		||||
        with pytest.raises(pytest.fail.Exception):
 | 
			
		||||
        with pytest.raises(Failed):
 | 
			
		||||
            metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "z"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_uses_no_fixture_error_indirect_false(self, testdir):
 | 
			
		||||
    def test_parametrize_uses_no_fixture_error_indirect_false(
 | 
			
		||||
        self, testdir: Testdir
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """The 'uses no fixture' error tells the user at collection time
 | 
			
		||||
        that the parametrize data they've set up doesn't correspond to the
 | 
			
		||||
        fixtures in their test function, rather than silently ignoring this
 | 
			
		||||
| 
						 | 
				
			
			@ -745,7 +755,9 @@ class TestMetafunc:
 | 
			
		|||
        result = testdir.runpytest("--collect-only")
 | 
			
		||||
        result.stdout.fnmatch_lines(["*uses no argument 'y'*"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_uses_no_fixture_error_indirect_true(self, testdir):
 | 
			
		||||
    def test_parametrize_uses_no_fixture_error_indirect_true(
 | 
			
		||||
        self, testdir: Testdir
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -765,7 +777,9 @@ class TestMetafunc:
 | 
			
		|||
        result = testdir.runpytest("--collect-only")
 | 
			
		||||
        result.stdout.fnmatch_lines(["*uses no fixture 'y'*"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_uses_no_fixture_error_indirect_string(self, testdir):
 | 
			
		||||
    def test_parametrize_indirect_uses_no_fixture_error_indirect_string(
 | 
			
		||||
        self, testdir: Testdir
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -782,7 +796,9 @@ class TestMetafunc:
 | 
			
		|||
        result = testdir.runpytest("--collect-only")
 | 
			
		||||
        result.stdout.fnmatch_lines(["*uses no fixture 'y'*"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_indirect_uses_no_fixture_error_indirect_list(self, testdir):
 | 
			
		||||
    def test_parametrize_indirect_uses_no_fixture_error_indirect_list(
 | 
			
		||||
        self, testdir: Testdir
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -799,7 +815,7 @@ class TestMetafunc:
 | 
			
		|||
        result = testdir.runpytest("--collect-only")
 | 
			
		||||
        result.stdout.fnmatch_lines(["*uses no fixture 'y'*"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_argument_not_in_indirect_list(self, testdir):
 | 
			
		||||
    def test_parametrize_argument_not_in_indirect_list(self, testdir: Testdir) -> None:
 | 
			
		||||
        """#714"""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -818,7 +834,7 @@ class TestMetafunc:
 | 
			
		|||
 | 
			
		||||
    def test_parametrize_gives_indicative_error_on_function_with_default_argument(
 | 
			
		||||
        self, testdir
 | 
			
		||||
    ):
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -833,7 +849,7 @@ class TestMetafunc:
 | 
			
		|||
            ["*already takes an argument 'y' with a default value"]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_functional(self, testdir):
 | 
			
		||||
    def test_parametrize_functional(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -854,7 +870,7 @@ class TestMetafunc:
 | 
			
		|||
            ["*test_simple*1-2*", "*test_simple*2-2*", "*2 passed*"]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_onearg(self):
 | 
			
		||||
    def test_parametrize_onearg(self) -> None:
 | 
			
		||||
        metafunc = self.Metafunc(lambda x: None)
 | 
			
		||||
        metafunc.parametrize("x", [1, 2])
 | 
			
		||||
        assert len(metafunc._calls) == 2
 | 
			
		||||
| 
						 | 
				
			
			@ -863,7 +879,7 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc._calls[1].funcargs == dict(x=2)
 | 
			
		||||
        assert metafunc._calls[1].id == "2"
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_onearg_indirect(self):
 | 
			
		||||
    def test_parametrize_onearg_indirect(self) -> None:
 | 
			
		||||
        metafunc = self.Metafunc(lambda x: None)
 | 
			
		||||
        metafunc.parametrize("x", [1, 2], indirect=True)
 | 
			
		||||
        assert metafunc._calls[0].params == dict(x=1)
 | 
			
		||||
| 
						 | 
				
			
			@ -871,7 +887,7 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc._calls[1].params == dict(x=2)
 | 
			
		||||
        assert metafunc._calls[1].id == "2"
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_twoargs(self):
 | 
			
		||||
    def test_parametrize_twoargs(self) -> None:
 | 
			
		||||
        metafunc = self.Metafunc(lambda x, y: None)
 | 
			
		||||
        metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)])
 | 
			
		||||
        assert len(metafunc._calls) == 2
 | 
			
		||||
| 
						 | 
				
			
			@ -880,7 +896,7 @@ class TestMetafunc:
 | 
			
		|||
        assert metafunc._calls[1].funcargs == dict(x=3, y=4)
 | 
			
		||||
        assert metafunc._calls[1].id == "3-4"
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_multiple_times(self, testdir):
 | 
			
		||||
    def test_parametrize_multiple_times(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -897,7 +913,7 @@ class TestMetafunc:
 | 
			
		|||
        assert result.ret == 1
 | 
			
		||||
        result.assert_outcomes(failed=6)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_CSV(self, testdir):
 | 
			
		||||
    def test_parametrize_CSV(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -909,7 +925,7 @@ class TestMetafunc:
 | 
			
		|||
        reprec = testdir.inline_run()
 | 
			
		||||
        reprec.assertoutcome(passed=2)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_class_scenarios(self, testdir):
 | 
			
		||||
    def test_parametrize_class_scenarios(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
        # same as doc/en/example/parametrize scenario example
 | 
			
		||||
| 
						 | 
				
			
			@ -951,7 +967,7 @@ class TestMetafunc:
 | 
			
		|||
        """
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_format_args(self):
 | 
			
		||||
    def test_format_args(self) -> None:
 | 
			
		||||
        def function1():
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -974,7 +990,7 @@ class TestMetafunc:
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
class TestMetafuncFunctional:
 | 
			
		||||
    def test_attributes(self, testdir):
 | 
			
		||||
    def test_attributes(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            # assumes that generate/provide runs in the same process
 | 
			
		||||
| 
						 | 
				
			
			@ -1004,7 +1020,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest(p, "-v")
 | 
			
		||||
        result.assert_outcomes(passed=2)
 | 
			
		||||
 | 
			
		||||
    def test_two_functions(self, testdir):
 | 
			
		||||
    def test_two_functions(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_generate_tests(metafunc):
 | 
			
		||||
| 
						 | 
				
			
			@ -1028,7 +1044,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_noself_in_method(self, testdir):
 | 
			
		||||
    def test_noself_in_method(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_generate_tests(metafunc):
 | 
			
		||||
| 
						 | 
				
			
			@ -1042,7 +1058,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest(p)
 | 
			
		||||
        result.assert_outcomes(passed=1)
 | 
			
		||||
 | 
			
		||||
    def test_generate_tests_in_class(self, testdir):
 | 
			
		||||
    def test_generate_tests_in_class(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            class TestClass(object):
 | 
			
		||||
| 
						 | 
				
			
			@ -1056,7 +1072,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest("-v", p)
 | 
			
		||||
        result.stdout.fnmatch_lines(["*test_myfunc*hello*PASS*", "*1 passed*"])
 | 
			
		||||
 | 
			
		||||
    def test_two_functions_not_same_instance(self, testdir):
 | 
			
		||||
    def test_two_functions_not_same_instance(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_generate_tests(metafunc):
 | 
			
		||||
| 
						 | 
				
			
			@ -1073,7 +1089,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
            ["*test_func*0*PASS*", "*test_func*1*PASS*", "*2 pass*"]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_issue28_setup_method_in_generate_tests(self, testdir):
 | 
			
		||||
    def test_issue28_setup_method_in_generate_tests(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_generate_tests(metafunc):
 | 
			
		||||
| 
						 | 
				
			
			@ -1089,7 +1105,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest(p)
 | 
			
		||||
        result.assert_outcomes(passed=1)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_functional2(self, testdir):
 | 
			
		||||
    def test_parametrize_functional2(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_generate_tests(metafunc):
 | 
			
		||||
| 
						 | 
				
			
			@ -1104,7 +1120,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
            ["*(1, 4)*", "*(1, 5)*", "*(2, 4)*", "*(2, 5)*", "*4 failed*"]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_and_inner_getfixturevalue(self, testdir):
 | 
			
		||||
    def test_parametrize_and_inner_getfixturevalue(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_generate_tests(metafunc):
 | 
			
		||||
| 
						 | 
				
			
			@ -1128,7 +1144,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest("-v", p)
 | 
			
		||||
        result.stdout.fnmatch_lines(["*test_func1*1*PASS*", "*1 passed*"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_on_setup_arg(self, testdir):
 | 
			
		||||
    def test_parametrize_on_setup_arg(self, testdir: Testdir) -> None:
 | 
			
		||||
        p = testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_generate_tests(metafunc):
 | 
			
		||||
| 
						 | 
				
			
			@ -1151,7 +1167,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest("-v", p)
 | 
			
		||||
        result.stdout.fnmatch_lines(["*test_func*1*PASS*", "*1 passed*"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_with_ids(self, testdir):
 | 
			
		||||
    def test_parametrize_with_ids(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makeini(
 | 
			
		||||
            """
 | 
			
		||||
            [pytest]
 | 
			
		||||
| 
						 | 
				
			
			@ -1175,7 +1191,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
            ["*test_function*basic*PASSED", "*test_function*advanced*FAILED"]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_without_ids(self, testdir):
 | 
			
		||||
    def test_parametrize_without_ids(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1195,7 +1211,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        """
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_with_None_in_ids(self, testdir):
 | 
			
		||||
    def test_parametrize_with_None_in_ids(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1217,7 +1233,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_fixture_parametrized_empty_ids(self, testdir):
 | 
			
		||||
    def test_fixture_parametrized_empty_ids(self, testdir: Testdir) -> None:
 | 
			
		||||
        """Fixtures parametrized with empty ids cause an internal error (#1849)."""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -1234,7 +1250,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest()
 | 
			
		||||
        result.stdout.fnmatch_lines(["* 1 skipped *"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrized_empty_ids(self, testdir):
 | 
			
		||||
    def test_parametrized_empty_ids(self, testdir: Testdir) -> None:
 | 
			
		||||
        """Tests parametrized with empty ids cause an internal error (#1849)."""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -1248,7 +1264,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest()
 | 
			
		||||
        result.stdout.fnmatch_lines(["* 1 skipped *"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrized_ids_invalid_type(self, testdir):
 | 
			
		||||
    def test_parametrized_ids_invalid_type(self, testdir: Testdir) -> None:
 | 
			
		||||
        """Test error with non-strings/non-ints, without generator (#1857)."""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -1267,7 +1283,9 @@ class TestMetafuncFunctional:
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_with_identical_ids_get_unique_names(self, testdir):
 | 
			
		||||
    def test_parametrize_with_identical_ids_get_unique_names(
 | 
			
		||||
        self, testdir: Testdir
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1286,7 +1304,9 @@ class TestMetafuncFunctional:
 | 
			
		|||
        )
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize(("scope", "length"), [("module", 2), ("function", 4)])
 | 
			
		||||
    def test_parametrize_scope_overrides(self, testdir, scope, length):
 | 
			
		||||
    def test_parametrize_scope_overrides(
 | 
			
		||||
        self, testdir: Testdir, scope: str, length: int
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1311,7 +1331,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        reprec = testdir.inline_run()
 | 
			
		||||
        reprec.assertoutcome(passed=5)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_issue323(self, testdir):
 | 
			
		||||
    def test_parametrize_issue323(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1329,7 +1349,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        reprec = testdir.inline_run("--collect-only")
 | 
			
		||||
        assert not reprec.getcalls("pytest_internalerror")
 | 
			
		||||
 | 
			
		||||
    def test_usefixtures_seen_in_generate_tests(self, testdir):
 | 
			
		||||
    def test_usefixtures_seen_in_generate_tests(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1345,7 +1365,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        reprec = testdir.runpytest()
 | 
			
		||||
        reprec.assert_outcomes(passed=1)
 | 
			
		||||
 | 
			
		||||
    def test_generate_tests_only_done_in_subdir(self, testdir):
 | 
			
		||||
    def test_generate_tests_only_done_in_subdir(self, testdir: Testdir) -> None:
 | 
			
		||||
        sub1 = testdir.mkpydir("sub1")
 | 
			
		||||
        sub2 = testdir.mkpydir("sub2")
 | 
			
		||||
        sub1.join("conftest.py").write(
 | 
			
		||||
| 
						 | 
				
			
			@ -1369,7 +1389,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        result = testdir.runpytest("--keep-duplicates", "-v", "-s", sub1, sub2, sub1)
 | 
			
		||||
        result.assert_outcomes(passed=3)
 | 
			
		||||
 | 
			
		||||
    def test_generate_same_function_names_issue403(self, testdir):
 | 
			
		||||
    def test_generate_same_function_names_issue403(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1387,7 +1407,7 @@ class TestMetafuncFunctional:
 | 
			
		|||
        reprec = testdir.runpytest()
 | 
			
		||||
        reprec.assert_outcomes(passed=4)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_misspelling(self, testdir):
 | 
			
		||||
    def test_parametrize_misspelling(self, testdir: Testdir) -> None:
 | 
			
		||||
        """#463"""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -1419,7 +1439,7 @@ class TestMetafuncFunctionalAuto:
 | 
			
		|||
    Tests related to automatically find out the correct scope for parametrized tests (#1832).
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_auto_scope(self, testdir):
 | 
			
		||||
    def test_parametrize_auto_scope(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1441,7 +1461,7 @@ class TestMetafuncFunctionalAuto:
 | 
			
		|||
        result = testdir.runpytest()
 | 
			
		||||
        result.stdout.fnmatch_lines(["* 3 passed *"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_auto_scope_indirect(self, testdir):
 | 
			
		||||
    def test_parametrize_auto_scope_indirect(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1464,7 +1484,7 @@ class TestMetafuncFunctionalAuto:
 | 
			
		|||
        result = testdir.runpytest()
 | 
			
		||||
        result.stdout.fnmatch_lines(["* 3 passed *"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_auto_scope_override_fixture(self, testdir):
 | 
			
		||||
    def test_parametrize_auto_scope_override_fixture(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1481,7 +1501,7 @@ class TestMetafuncFunctionalAuto:
 | 
			
		|||
        result = testdir.runpytest()
 | 
			
		||||
        result.stdout.fnmatch_lines(["* 2 passed *"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_all_indirects(self, testdir):
 | 
			
		||||
    def test_parametrize_all_indirects(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1508,11 +1528,13 @@ class TestMetafuncFunctionalAuto:
 | 
			
		|||
        result = testdir.runpytest()
 | 
			
		||||
        result.stdout.fnmatch_lines(["* 3 passed *"])
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_some_arguments_auto_scope(self, testdir, monkeypatch):
 | 
			
		||||
    def test_parametrize_some_arguments_auto_scope(
 | 
			
		||||
        self, testdir: Testdir, monkeypatch
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """Integration test for (#3941)"""
 | 
			
		||||
        class_fix_setup = []
 | 
			
		||||
        class_fix_setup = []  # type: List[object]
 | 
			
		||||
        monkeypatch.setattr(sys, "class_fix_setup", class_fix_setup, raising=False)
 | 
			
		||||
        func_fix_setup = []
 | 
			
		||||
        func_fix_setup = []  # type: List[object]
 | 
			
		||||
        monkeypatch.setattr(sys, "func_fix_setup", func_fix_setup, raising=False)
 | 
			
		||||
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
| 
						 | 
				
			
			@ -1541,7 +1563,7 @@ class TestMetafuncFunctionalAuto:
 | 
			
		|||
        assert func_fix_setup == [True] * 4
 | 
			
		||||
        assert class_fix_setup == [10, 20]
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_issue634(self, testdir):
 | 
			
		||||
    def test_parametrize_issue634(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1579,7 +1601,7 @@ class TestMetafuncFunctionalAuto:
 | 
			
		|||
class TestMarkersWithParametrization:
 | 
			
		||||
    """#308"""
 | 
			
		||||
 | 
			
		||||
    def test_simple_mark(self, testdir):
 | 
			
		||||
    def test_simple_mark(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1600,7 +1622,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        assert "bar" in items[1].keywords
 | 
			
		||||
        assert "bar" not in items[2].keywords
 | 
			
		||||
 | 
			
		||||
    def test_select_based_on_mark(self, testdir):
 | 
			
		||||
    def test_select_based_on_mark(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1619,7 +1641,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        assert len(skipped) == 0
 | 
			
		||||
        assert len(fail) == 0
 | 
			
		||||
 | 
			
		||||
    def test_simple_xfail(self, testdir):
 | 
			
		||||
    def test_simple_xfail(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1636,7 +1658,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        # xfail is skip??
 | 
			
		||||
        reprec.assertoutcome(passed=2, skipped=1)
 | 
			
		||||
 | 
			
		||||
    def test_simple_xfail_single_argname(self, testdir):
 | 
			
		||||
    def test_simple_xfail_single_argname(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1652,7 +1674,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        reprec = testdir.inline_run()
 | 
			
		||||
        reprec.assertoutcome(passed=2, skipped=1)
 | 
			
		||||
 | 
			
		||||
    def test_xfail_with_arg(self, testdir):
 | 
			
		||||
    def test_xfail_with_arg(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1668,7 +1690,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        reprec = testdir.inline_run()
 | 
			
		||||
        reprec.assertoutcome(passed=2, skipped=1)
 | 
			
		||||
 | 
			
		||||
    def test_xfail_with_kwarg(self, testdir):
 | 
			
		||||
    def test_xfail_with_kwarg(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1684,7 +1706,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        reprec = testdir.inline_run()
 | 
			
		||||
        reprec.assertoutcome(passed=2, skipped=1)
 | 
			
		||||
 | 
			
		||||
    def test_xfail_with_arg_and_kwarg(self, testdir):
 | 
			
		||||
    def test_xfail_with_arg_and_kwarg(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1701,7 +1723,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        reprec.assertoutcome(passed=2, skipped=1)
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("strict", [True, False])
 | 
			
		||||
    def test_xfail_passing_is_xpass(self, testdir, strict):
 | 
			
		||||
    def test_xfail_passing_is_xpass(self, testdir: Testdir, strict: bool) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1722,7 +1744,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        passed, failed = (2, 1) if strict else (3, 0)
 | 
			
		||||
        reprec.assertoutcome(passed=passed, failed=failed)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_called_in_generate_tests(self, testdir):
 | 
			
		||||
    def test_parametrize_called_in_generate_tests(self, testdir: Testdir) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1745,7 +1767,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        reprec = testdir.inline_run()
 | 
			
		||||
        reprec.assertoutcome(passed=2, skipped=2)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_ID_generation_string_int_works(self, testdir):
 | 
			
		||||
    def test_parametrize_ID_generation_string_int_works(self, testdir: Testdir) -> None:
 | 
			
		||||
        """#290"""
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
| 
						 | 
				
			
			@ -1764,7 +1786,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        reprec.assertoutcome(passed=2)
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("strict", [True, False])
 | 
			
		||||
    def test_parametrize_marked_value(self, testdir, strict):
 | 
			
		||||
    def test_parametrize_marked_value(self, testdir: Testdir, strict: bool) -> None:
 | 
			
		||||
        s = """
 | 
			
		||||
            import pytest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1788,7 +1810,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        passed, failed = (0, 2) if strict else (2, 0)
 | 
			
		||||
        reprec.assertoutcome(passed=passed, failed=failed)
 | 
			
		||||
 | 
			
		||||
    def test_pytest_make_parametrize_id(self, testdir):
 | 
			
		||||
    def test_pytest_make_parametrize_id(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makeconftest(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_make_parametrize_id(config, val):
 | 
			
		||||
| 
						 | 
				
			
			@ -1807,7 +1829,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        result = testdir.runpytest("-v")
 | 
			
		||||
        result.stdout.fnmatch_lines(["*test_func*0*PASS*", "*test_func*2*PASS*"])
 | 
			
		||||
 | 
			
		||||
    def test_pytest_make_parametrize_id_with_argname(self, testdir):
 | 
			
		||||
    def test_pytest_make_parametrize_id_with_argname(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makeconftest(
 | 
			
		||||
            """
 | 
			
		||||
            def pytest_make_parametrize_id(config, val, argname):
 | 
			
		||||
| 
						 | 
				
			
			@ -1832,7 +1854,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
            ["*test_func_a*0*PASS*", "*test_func_a*2*PASS*", "*test_func_b*10*PASS*"]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_positional_args(self, testdir):
 | 
			
		||||
    def test_parametrize_positional_args(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1845,7 +1867,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
        result = testdir.runpytest()
 | 
			
		||||
        result.assert_outcomes(passed=1)
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_iterator(self, testdir):
 | 
			
		||||
    def test_parametrize_iterator(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import itertools
 | 
			
		||||
| 
						 | 
				
			
			@ -1881,7 +1903,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_explicit_parameters_func(self, testdir):
 | 
			
		||||
    def test_parametrize_explicit_parameters_func(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			@ -1905,7 +1927,7 @@ class TestMarkersWithParametrization:
 | 
			
		|||
            ]
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_parametrize_explicit_parameters_method(self, testdir):
 | 
			
		||||
    def test_parametrize_explicit_parameters_method(self, testdir: Testdir) -> None:
 | 
			
		||||
        testdir.makepyfile(
 | 
			
		||||
            """
 | 
			
		||||
            import pytest
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue