Move fixtures.py::add_funcarg_pseudo_fixture_def to Metafunc.parametrize (#11220)
To remove fixtures.py::add_funcargs_pseudo_fixture_def and add its logic i.e. registering funcargs as params and making corresponding fixturedefs, right to Metafunc.parametrize in which parametrization takes place. To remove funcargs from metafunc attributes as we populate metafunc params and make pseudo fixturedefs simultaneously and there's no need to keep funcargs separately.
This commit is contained in:
@@ -23,6 +23,7 @@ from _pytest.compat import getfuncargnames
|
||||
from _pytest.compat import NOTSET
|
||||
from _pytest.outcomes import fail
|
||||
from _pytest.pytester import Pytester
|
||||
from _pytest.python import Function
|
||||
from _pytest.python import IdMaker
|
||||
from _pytest.scope import Scope
|
||||
|
||||
@@ -33,11 +34,19 @@ class TestMetafunc:
|
||||
# on the funcarg level, so we don't need a full blown
|
||||
# initialization.
|
||||
class FuncFixtureInfoMock:
|
||||
name2fixturedefs = None
|
||||
name2fixturedefs: Dict[str, List[fixtures.FixtureDef[object]]] = {}
|
||||
|
||||
def __init__(self, names):
|
||||
self.names_closure = names
|
||||
|
||||
@dataclasses.dataclass
|
||||
class FixtureManagerMock:
|
||||
config: Any
|
||||
|
||||
@dataclasses.dataclass
|
||||
class SessionMock:
|
||||
_fixturemanager: FixtureManagerMock
|
||||
|
||||
@dataclasses.dataclass
|
||||
class DefinitionMock(python.FunctionDefinition):
|
||||
_nodeid: str
|
||||
@@ -46,6 +55,8 @@ class TestMetafunc:
|
||||
names = getfuncargnames(func)
|
||||
fixtureinfo: Any = FuncFixtureInfoMock(names)
|
||||
definition: Any = DefinitionMock._create(obj=func, _nodeid="mock::nodeid")
|
||||
definition._fixtureinfo = fixtureinfo
|
||||
definition.session = SessionMock(FixtureManagerMock({}))
|
||||
return python.Metafunc(definition, fixtureinfo, config, _ispytest=True)
|
||||
|
||||
def test_no_funcargs(self) -> None:
|
||||
@@ -98,7 +109,7 @@ class TestMetafunc:
|
||||
# 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]
|
||||
assert [(x.funcargs, x.id) for x in metafunc._calls] == [
|
||||
assert [(x.params, x.id) for x in metafunc._calls] == [
|
||||
({"x": 1}, "0"),
|
||||
({"x": 2}, "2"),
|
||||
]
|
||||
@@ -714,8 +725,6 @@ class TestMetafunc:
|
||||
metafunc.parametrize("x", [1], indirect=True)
|
||||
metafunc.parametrize("y", [2, 3], indirect=True)
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == {}
|
||||
assert metafunc._calls[1].funcargs == {}
|
||||
assert metafunc._calls[0].params == dict(x=1, y=2)
|
||||
assert metafunc._calls[1].params == dict(x=1, y=3)
|
||||
|
||||
@@ -727,8 +736,10 @@ class TestMetafunc:
|
||||
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize("x, y", [("a", "b")], indirect=["x"])
|
||||
assert metafunc._calls[0].funcargs == dict(y="b")
|
||||
assert metafunc._calls[0].params == dict(x="a")
|
||||
assert metafunc._calls[0].params == dict(x="a", y="b")
|
||||
# Since `y` is a direct parameter, its pseudo-fixture would
|
||||
# be registered.
|
||||
assert list(metafunc._arg2fixturedefs.keys()) == ["y"]
|
||||
|
||||
def test_parametrize_indirect_list_all(self) -> None:
|
||||
"""#714"""
|
||||
@@ -738,8 +749,8 @@ class TestMetafunc:
|
||||
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "y"])
|
||||
assert metafunc._calls[0].funcargs == {}
|
||||
assert metafunc._calls[0].params == dict(x="a", y="b")
|
||||
assert list(metafunc._arg2fixturedefs.keys()) == []
|
||||
|
||||
def test_parametrize_indirect_list_empty(self) -> None:
|
||||
"""#714"""
|
||||
@@ -749,8 +760,8 @@ class TestMetafunc:
|
||||
|
||||
metafunc = self.Metafunc(func)
|
||||
metafunc.parametrize("x, y", [("a", "b")], indirect=[])
|
||||
assert metafunc._calls[0].funcargs == dict(x="a", y="b")
|
||||
assert metafunc._calls[0].params == {}
|
||||
assert metafunc._calls[0].params == dict(x="a", y="b")
|
||||
assert list(metafunc._arg2fixturedefs.keys()) == ["x", "y"]
|
||||
|
||||
def test_parametrize_indirect_wrong_type(self) -> None:
|
||||
def func(x, y):
|
||||
@@ -944,9 +955,9 @@ class TestMetafunc:
|
||||
metafunc = self.Metafunc(lambda x: None)
|
||||
metafunc.parametrize("x", [1, 2])
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == dict(x=1)
|
||||
assert metafunc._calls[0].params == dict(x=1)
|
||||
assert metafunc._calls[0].id == "1"
|
||||
assert metafunc._calls[1].funcargs == dict(x=2)
|
||||
assert metafunc._calls[1].params == dict(x=2)
|
||||
assert metafunc._calls[1].id == "2"
|
||||
|
||||
def test_parametrize_onearg_indirect(self) -> None:
|
||||
@@ -961,11 +972,45 @@ class TestMetafunc:
|
||||
metafunc = self.Metafunc(lambda x, y: None)
|
||||
metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)])
|
||||
assert len(metafunc._calls) == 2
|
||||
assert metafunc._calls[0].funcargs == dict(x=1, y=2)
|
||||
assert metafunc._calls[0].params == dict(x=1, y=2)
|
||||
assert metafunc._calls[0].id == "1-2"
|
||||
assert metafunc._calls[1].funcargs == dict(x=3, y=4)
|
||||
assert metafunc._calls[1].params == dict(x=3, y=4)
|
||||
assert metafunc._calls[1].id == "3-4"
|
||||
|
||||
def test_high_scoped_parametrize_reordering(self, pytester: Pytester) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
@pytest.mark.parametrize("arg2", [3, 4])
|
||||
@pytest.mark.parametrize("arg1", [0, 1, 2], scope='module')
|
||||
def test1(arg1, arg2):
|
||||
pass
|
||||
|
||||
def test2():
|
||||
pass
|
||||
|
||||
@pytest.mark.parametrize("arg1", [0, 1, 2], scope='module')
|
||||
def test3(arg1):
|
||||
pass
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest("--collect-only")
|
||||
result.stdout.re_match_lines(
|
||||
[
|
||||
r" <Function test1\[0-3\]>",
|
||||
r" <Function test1\[0-4\]>",
|
||||
r" <Function test3\[0\]>",
|
||||
r" <Function test1\[1-3\]>",
|
||||
r" <Function test1\[1-4\]>",
|
||||
r" <Function test3\[1\]>",
|
||||
r" <Function test1\[2-3\]>",
|
||||
r" <Function test1\[2-4\]>",
|
||||
r" <Function test3\[2\]>",
|
||||
r" <Function test2>",
|
||||
]
|
||||
)
|
||||
|
||||
def test_parametrize_multiple_times(self, pytester: Pytester) -> None:
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
@@ -1505,6 +1550,38 @@ class TestMetafuncFunctional:
|
||||
result = pytester.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
def test_parametrize_module_level_test_with_class_scope(
|
||||
self, pytester: Pytester
|
||||
) -> None:
|
||||
"""
|
||||
Test that a class-scoped parametrization without a corresponding `Class`
|
||||
gets module scope, i.e. we only create a single FixtureDef for it per module.
|
||||
"""
|
||||
module = pytester.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
@pytest.mark.parametrize("x", [0, 1], scope="class")
|
||||
def test_1(x):
|
||||
pass
|
||||
|
||||
@pytest.mark.parametrize("x", [1, 2], scope="module")
|
||||
def test_2(x):
|
||||
pass
|
||||
"""
|
||||
)
|
||||
test_1_0, _, test_2_0, _ = pytester.genitems((pytester.getmodulecol(module),))
|
||||
|
||||
assert isinstance(test_1_0, Function)
|
||||
assert test_1_0.name == "test_1[0]"
|
||||
test_1_fixture_x = test_1_0._fixtureinfo.name2fixturedefs["x"][-1]
|
||||
|
||||
assert isinstance(test_2_0, Function)
|
||||
assert test_2_0.name == "test_2[1]"
|
||||
test_2_fixture_x = test_2_0._fixtureinfo.name2fixturedefs["x"][-1]
|
||||
|
||||
assert test_1_fixture_x is test_2_fixture_x
|
||||
|
||||
def test_reordering_with_scopeless_and_just_indirect_parametrization(
|
||||
self, pytester: Pytester
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user