Skip to content

Commit 9ac1f5c

Browse files
A few improvements
1 parent 96be57a commit 9ac1f5c

File tree

2 files changed

+22
-60
lines changed

2 files changed

+22
-60
lines changed

src/_pytest/python.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,11 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]:
498498
if not metafunc._calls:
499499
yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo)
500500
else:
501-
# Dynamic direct parametrization may have shadowed some fixtures,
502-
# so make sure we update what the function really needs.
501+
# Direct parametrizations taking place in module/class-specific
502+
# `metafunc.parametrize` calls may have shadowed some fixtures, so make sure
503+
# we update what the function really needs a.k.a its fixture closure. Note that
504+
# direct parametrizations using `@pytest.mark.parametrize` have already been considered
505+
# into making the closure using `ignore_args` arg to `getfixtureclosure`.
503506
fixtureinfo.prune_dependency_tree()
504507

505508
for callspec in metafunc._calls:
@@ -1170,7 +1173,7 @@ def get_direct_param_fixture_func(request: FixtureRequest) -> Any:
11701173
return request.param
11711174

11721175

1173-
# Used for storing artificial fixturedefs for direct parametrization.
1176+
# Used for storing pseudo fixturedefs for direct parametrization.
11741177
name2pseudofixturedef_key = StashKey[Dict[str, FixtureDef[Any]]]()
11751178

11761179

@@ -1330,8 +1333,8 @@ def parametrize(
13301333
object.__setattr__(_param_mark._param_ids_from, "_param_ids_generated", ids)
13311334

13321335
# Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering
1333-
# artificial FixtureDef's so that later at test execution time we can rely
1334-
# on a proper FixtureDef to exist for fixture setup.
1336+
# artificial "pseudo" FixtureDef's so that later at test execution time we can
1337+
# rely on a proper FixtureDef to exist for fixture setup.
13351338
arg2fixturedefs = self._arg2fixturedefs
13361339
node = None
13371340
# If we have a scope that is higher than function, we need

testing/python/metafunc.py

Lines changed: 14 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from _pytest.compat import NOTSET
2424
from _pytest.outcomes import fail
2525
from _pytest.pytester import Pytester
26+
from _pytest.python import Function
2627
from _pytest.python import IdMaker
2728
from _pytest.scope import Scope
2829

@@ -974,16 +975,6 @@ def test_parametrize_twoargs(self) -> None:
974975
assert metafunc._calls[1].params == dict(x=3, y=4)
975976
assert metafunc._calls[1].id == "3-4"
976977

977-
@pytest.mark.xfail(reason="Will pass upon merging PR#11257")
978-
def test_parametrize_with_duplicate_values(self) -> None:
979-
metafunc = self.Metafunc(lambda x, y: None)
980-
metafunc.parametrize(("x", "y"), [(1, 2), (3, 4), (1, 5), (2, 2)])
981-
assert len(metafunc._calls) == 4
982-
assert metafunc._calls[0].indices == dict(x=0, y=0)
983-
assert metafunc._calls[1].indices == dict(x=1, y=1)
984-
assert metafunc._calls[2].indices == dict(x=0, y=2)
985-
assert metafunc._calls[3].indices == dict(x=2, y=0)
986-
987978
def test_high_scoped_parametrize_reordering(self, pytester: Pytester) -> None:
988979
pytester.makepyfile(
989980
"""
@@ -1018,36 +1009,6 @@ def test3(arg1):
10181009
]
10191010
)
10201011

1021-
@pytest.mark.xfail(reason="Will pass upon merging PR#11257")
1022-
def test_high_scoped_parametrize_with_duplicate_values_reordering(
1023-
self, pytester: Pytester
1024-
) -> None:
1025-
pytester.makepyfile(
1026-
"""
1027-
import pytest
1028-
1029-
@pytest.fixture(scope='module')
1030-
def fixture1(request):
1031-
pass
1032-
1033-
@pytest.fixture(scope='module')
1034-
def fixture2(request):
1035-
pass
1036-
1037-
@pytest.mark.parametrize("fixture1, fixture2", [("a", 0), ("b", 1), ("a", 2)], indirect=True)
1038-
def test(fixture1, fixture2):
1039-
pass
1040-
"""
1041-
)
1042-
result = pytester.runpytest("--collect-only")
1043-
result.stdout.re_match_lines(
1044-
[
1045-
r" <Function test\[a-0\]>",
1046-
r" <Function test\[a-2\]>",
1047-
r" <Function test\[b-1\]>",
1048-
]
1049-
)
1050-
10511012
def test_parametrize_multiple_times(self, pytester: Pytester) -> None:
10521013
pytester.makepyfile(
10531014
"""
@@ -1590,29 +1551,27 @@ def test_it(x): pass
15901551
def test_parametrize_module_level_test_with_class_scope(
15911552
self, pytester: Pytester
15921553
) -> None:
1593-
pytester.makepyfile(
1554+
module = pytester.makepyfile(
15941555
"""
15951556
import pytest
15961557
1597-
@pytest.fixture
1598-
def item(request):
1599-
return request._pyfuncitem
1600-
1601-
fixturedef = None
1602-
16031558
@pytest.mark.parametrize("x", [0, 1], scope="class")
1604-
def test_1(item, x):
1605-
global fixturedef
1606-
fixturedef = item._fixtureinfo.name2fixturedefs['x'][-1]
1559+
def test_1(x):
1560+
pass
16071561
16081562
@pytest.mark.parametrize("x", [1, 2], scope="module")
1609-
def test_2(item, x):
1610-
global fixturedef
1611-
assert fixturedef == item._fixtureinfo.name2fixturedefs['x'][-1]
1563+
def test_2(x):
1564+
pass
16121565
"""
16131566
)
1614-
result = pytester.runpytest()
1615-
assert result.ret == 0
1567+
test_1_0, _, test_2_0, _ = pytester.genitems((pytester.getmodulecol(module),))
1568+
test_1_fixture_x = cast(Function, test_1_0)._fixtureinfo.name2fixturedefs["x"][
1569+
-1
1570+
]
1571+
test_2_fixture_x = cast(Function, test_2_0)._fixtureinfo.name2fixturedefs["x"][
1572+
-1
1573+
]
1574+
assert test_1_fixture_x == test_2_fixture_x
16161575

16171576

16181577
class TestMetafuncFunctionalAuto:

0 commit comments

Comments
 (0)