A few improvements
This commit is contained in:
parent
96be57a3d0
commit
40b2c09ecf
|
@ -14,7 +14,6 @@ from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import cast
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import final
|
from typing import final
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
@ -498,8 +497,11 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
if not metafunc._calls:
|
if not metafunc._calls:
|
||||||
yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo)
|
yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo)
|
||||||
else:
|
else:
|
||||||
# Dynamic direct parametrization may have shadowed some fixtures,
|
# Direct parametrizations taking place in module/class-specific
|
||||||
# so make sure we update what the function really needs.
|
# `metafunc.parametrize` calls may have shadowed some fixtures, so make sure
|
||||||
|
# we update what the function really needs a.k.a its fixture closure. Note that
|
||||||
|
# direct parametrizations using `@pytest.mark.parametrize` have already been considered
|
||||||
|
# into making the closure using `ignore_args` arg to `getfixtureclosure`.
|
||||||
fixtureinfo.prune_dependency_tree()
|
fixtureinfo.prune_dependency_tree()
|
||||||
|
|
||||||
for callspec in metafunc._calls:
|
for callspec in metafunc._calls:
|
||||||
|
@ -1170,7 +1172,7 @@ def get_direct_param_fixture_func(request: FixtureRequest) -> Any:
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
|
|
||||||
# Used for storing artificial fixturedefs for direct parametrization.
|
# Used for storing pseudo fixturedefs for direct parametrization.
|
||||||
name2pseudofixturedef_key = StashKey[Dict[str, FixtureDef[Any]]]()
|
name2pseudofixturedef_key = StashKey[Dict[str, FixtureDef[Any]]]()
|
||||||
|
|
||||||
|
|
||||||
|
@ -1330,8 +1332,8 @@ class Metafunc:
|
||||||
object.__setattr__(_param_mark._param_ids_from, "_param_ids_generated", ids)
|
object.__setattr__(_param_mark._param_ids_from, "_param_ids_generated", ids)
|
||||||
|
|
||||||
# Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering
|
# Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering
|
||||||
# artificial FixtureDef's so that later at test execution time we can rely
|
# artificial "pseudo" FixtureDef's so that later at test execution time we can
|
||||||
# on a proper FixtureDef to exist for fixture setup.
|
# rely on a proper FixtureDef to exist for fixture setup.
|
||||||
arg2fixturedefs = self._arg2fixturedefs
|
arg2fixturedefs = self._arg2fixturedefs
|
||||||
node = None
|
node = None
|
||||||
# If we have a scope that is higher than function, we need
|
# If we have a scope that is higher than function, we need
|
||||||
|
@ -1339,7 +1341,8 @@ class Metafunc:
|
||||||
# a per-scope basis. We thus store and cache the fixturedef on the
|
# a per-scope basis. We thus store and cache the fixturedef on the
|
||||||
# node related to the scope.
|
# node related to the scope.
|
||||||
if scope_ is not Scope.Function:
|
if scope_ is not Scope.Function:
|
||||||
collector = cast(nodes.Node, self.definition.parent)
|
collector = self.definition.parent
|
||||||
|
assert collector is not None
|
||||||
node = get_scope_node(collector, scope_)
|
node = get_scope_node(collector, scope_)
|
||||||
if node is None:
|
if node is None:
|
||||||
# If used class scope and there is no class, use module-level
|
# If used class scope and there is no class, use module-level
|
||||||
|
|
|
@ -23,6 +23,7 @@ from _pytest.compat import getfuncargnames
|
||||||
from _pytest.compat import NOTSET
|
from _pytest.compat import NOTSET
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
|
from _pytest.python import Function
|
||||||
from _pytest.python import IdMaker
|
from _pytest.python import IdMaker
|
||||||
from _pytest.scope import Scope
|
from _pytest.scope import Scope
|
||||||
|
|
||||||
|
@ -974,16 +975,6 @@ class TestMetafunc:
|
||||||
assert metafunc._calls[1].params == dict(x=3, y=4)
|
assert metafunc._calls[1].params == dict(x=3, y=4)
|
||||||
assert metafunc._calls[1].id == "3-4"
|
assert metafunc._calls[1].id == "3-4"
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="Will pass upon merging PR#11257")
|
|
||||||
def test_parametrize_with_duplicate_values(self) -> None:
|
|
||||||
metafunc = self.Metafunc(lambda x, y: None)
|
|
||||||
metafunc.parametrize(("x", "y"), [(1, 2), (3, 4), (1, 5), (2, 2)])
|
|
||||||
assert len(metafunc._calls) == 4
|
|
||||||
assert metafunc._calls[0].indices == dict(x=0, y=0)
|
|
||||||
assert metafunc._calls[1].indices == dict(x=1, y=1)
|
|
||||||
assert metafunc._calls[2].indices == dict(x=0, y=2)
|
|
||||||
assert metafunc._calls[3].indices == dict(x=2, y=0)
|
|
||||||
|
|
||||||
def test_high_scoped_parametrize_reordering(self, pytester: Pytester) -> None:
|
def test_high_scoped_parametrize_reordering(self, pytester: Pytester) -> None:
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1018,36 +1009,6 @@ class TestMetafunc:
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@pytest.mark.xfail(reason="Will pass upon merging PR#11257")
|
|
||||||
def test_high_scoped_parametrize_with_duplicate_values_reordering(
|
|
||||||
self, pytester: Pytester
|
|
||||||
) -> None:
|
|
||||||
pytester.makepyfile(
|
|
||||||
"""
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
|
||||||
def fixture1(request):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
|
||||||
def fixture2(request):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("fixture1, fixture2", [("a", 0), ("b", 1), ("a", 2)], indirect=True)
|
|
||||||
def test(fixture1, fixture2):
|
|
||||||
pass
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
result = pytester.runpytest("--collect-only")
|
|
||||||
result.stdout.re_match_lines(
|
|
||||||
[
|
|
||||||
r" <Function test\[a-0\]>",
|
|
||||||
r" <Function test\[a-2\]>",
|
|
||||||
r" <Function test\[b-1\]>",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_parametrize_multiple_times(self, pytester: Pytester) -> None:
|
def test_parametrize_multiple_times(self, pytester: Pytester) -> None:
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -1590,29 +1551,27 @@ class TestMetafuncFunctional:
|
||||||
def test_parametrize_module_level_test_with_class_scope(
|
def test_parametrize_module_level_test_with_class_scope(
|
||||||
self, pytester: Pytester
|
self, pytester: Pytester
|
||||||
) -> None:
|
) -> None:
|
||||||
pytester.makepyfile(
|
module = pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def item(request):
|
|
||||||
return request._pyfuncitem
|
|
||||||
|
|
||||||
fixturedef = None
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("x", [0, 1], scope="class")
|
@pytest.mark.parametrize("x", [0, 1], scope="class")
|
||||||
def test_1(item, x):
|
def test_1(x):
|
||||||
global fixturedef
|
pass
|
||||||
fixturedef = item._fixtureinfo.name2fixturedefs['x'][-1]
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("x", [1, 2], scope="module")
|
@pytest.mark.parametrize("x", [1, 2], scope="module")
|
||||||
def test_2(item, x):
|
def test_2(x):
|
||||||
global fixturedef
|
pass
|
||||||
assert fixturedef == item._fixtureinfo.name2fixturedefs['x'][-1]
|
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result = pytester.runpytest()
|
test_1_0, _, test_2_0, _ = pytester.genitems((pytester.getmodulecol(module),))
|
||||||
assert result.ret == 0
|
test_1_fixture_x = cast(Function, test_1_0)._fixtureinfo.name2fixturedefs["x"][
|
||||||
|
-1
|
||||||
|
]
|
||||||
|
test_2_fixture_x = cast(Function, test_2_0)._fixtureinfo.name2fixturedefs["x"][
|
||||||
|
-1
|
||||||
|
]
|
||||||
|
assert test_1_fixture_x == test_2_fixture_x
|
||||||
|
|
||||||
|
|
||||||
class TestMetafuncFunctionalAuto:
|
class TestMetafuncFunctionalAuto:
|
||||||
|
|
Loading…
Reference in New Issue