From 47c76694f8d4c76a2d7af49c3bb74769f1a9196e Mon Sep 17 00:00:00 2001 From: Aleksandr Brodin Date: Tue, 8 Aug 2023 17:20:27 +0700 Subject: [PATCH] support usefixtures with parametrize --- src/_pytest/python.py | 14 +++++++++++++- testing/python/metafunc.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index cbb82e390..e2c81e7eb 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -507,7 +507,7 @@ class PyCollector(PyobjMixin, nodes.Collector): for callspec in metafunc._calls: subname = f"{name}[{callspec.id}]" - yield Function.from_parent( + node = Function.from_parent( self, name=subname, callspec=callspec, @@ -515,6 +515,18 @@ class PyCollector(PyobjMixin, nodes.Collector): keywords={callspec.id: True}, originalname=name, ) + # if usefixtures is added via a parameter, then there will be + # fixtures missing from the node.fixturenames + callspec_usefixtures = tuple( + arg + for mark in node.iter_markers(name="usefixtures") + for arg in mark.args + if arg not in node.fixturenames + ) + if callspec_usefixtures: + # node.fixturenames must be unique for this parameter + node.fixturenames = [*node.fixturenames, *callspec_usefixtures] + yield node def importtestmodule( diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 4ee9e32d6..fa9f44536 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -2112,3 +2112,31 @@ class TestMarkersWithParametrization: "*= 6 passed in *", ] ) + + def test_simple_usefixtures_single_argname(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def some_fixture(): + pytest.skip() + + @pytest.mark.parametrize("val", [ + 1, + pytest.param(2, marks=pytest.mark.usefixtures('some_fixture')), + 3, + ]) + def test_foo(request, val): + assert val + """ + ) + result = pytester.runpytest("-vv", "-s") + result.assert_outcomes(passed=2, skipped=1) + result.stdout.fnmatch_lines( + [ + "test_simple_usefixtures_single_argname.py::test_foo[1] PASSED", + "test_simple_usefixtures_single_argname.py::test_foo[2] SKIPPED", + "test_simple_usefixtures_single_argname.py::test_foo[3] PASSED", + ] + )