From 60f6625b71b5552af02a4830e3d520f5ab6838e4 Mon Sep 17 00:00:00 2001 From: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Date: Sat, 25 Jul 2026 18:07:13 -0700 Subject: [PATCH] fix: avoid deprecated nodeid argument to _register_fixture Injecting a step's target_fixture called FixtureManager._register_fixture(nodeid=...). pytest 9.1 deprecated the nodeid argument in favour of node, so every scenario using a target_fixture emitted PytestRemovedIn10Warning, and suites that turn deprecation warnings into errors failed at collection. Pass node=request.node on pytest >= 9.1 and keep nodeid on older versions, matching the existing version-branching in compat.py. Added a regression test asserting the injection scenario runs clean under -W error::DeprecationWarning; it fails without this change. --- CHANGES.rst | 1 + src/pytest_bdd/compat.py | 10 ++++++++-- tests/steps/test_given.py | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 2706c8aeb..1272af2ad 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -34,6 +34,7 @@ Fixed * Backslashes in datatable and examples table cells are no longer over-quoted. A cell containing a single backslash now reaches the step as a single backslash, matching the Gherkin escaping rules. If you compensated by doubling backslashes in feature files, undo that. `#769 `_ * Made type annotations stronger and removed most of the ``typing.Any`` usages and ``# type: ignore`` annotations. `#658 `_ * Empty docstrings are now correctly forwarded to step functions as an empty string instead of being silently dropped, which previously caused pytest to report a missing ``docstring`` fixture. `#809 `_ +* Injecting a ``target_fixture`` no longer emits ``PytestRemovedIn10Warning`` on pytest 9.1+, which deprecated passing ``nodeid`` to ``_register_fixture``. `#823 `_ Security ++++++++ diff --git a/src/pytest_bdd/compat.py b/src/pytest_bdd/compat.py index 18829d46d..5999a1bd2 100644 --- a/src/pytest_bdd/compat.py +++ b/src/pytest_bdd/compat.py @@ -25,11 +25,17 @@ def inject_fixture(request: FixtureRequest, arg: str, value: object) -> None: :param arg: argument name :param value: argument value """ - # Ensure there's a fixture definition for the argument + # Ensure there's a fixture definition for the argument. + # pytest 9.1 deprecated the ``nodeid`` argument in favour of ``node``. + scoping: dict[str, object] + if pytest_version.release >= (9, 1): + scoping = {"node": request.node} + else: + scoping = {"nodeid": request.node.nodeid} request._fixturemanager._register_fixture( name=arg, func=lambda: value, - nodeid=request.node.nodeid, + **scoping, # type: ignore[arg-type] ) # Note the fixture we just registered will have a lower priority # if there was already one registered, so we need to force its value diff --git a/tests/steps/test_given.py b/tests/steps/test_given.py index 469befbe6..5a0cc7041 100644 --- a/tests/steps/test_given.py +++ b/tests/steps/test_given.py @@ -41,3 +41,42 @@ def _(foo): ) result = pytester.runpytest() result.assert_outcomes(passed=1) + + +def test_given_injection_no_deprecation_warning(pytester): + """Injecting a target fixture must not emit pytest deprecation warnings.""" + pytester.makefile( + ".feature", + given=textwrap.dedent( + """\ + Feature: Given + Scenario: Test given fixture injection + Given I have injecting given + Then foo should be "injected foo" + """ + ), + ) + pytester.makepyfile( + textwrap.dedent( + """\ + from pytest_bdd import given, then, scenario + + @scenario("given.feature", "Test given fixture injection") + def test_given(): + pass + + + @given("I have injecting given", target_fixture="foo") + def _(): + return "injected foo" + + + @then('foo should be "injected foo"') + def _(foo): + assert foo == "injected foo" + + """ + ) + ) + result = pytester.runpytest("-W", "error::DeprecationWarning", "-W", "error::PendingDeprecationWarning") + result.assert_outcomes(passed=1)