Skip to content

Commit 865fbe0

Browse files
committed
Fix step fixture injection
1 parent d517a80 commit 865fbe0

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

CHANGES.rst

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Changelog
33

44
Unreleased
55
----------
6+
- Fix an issue when only the first Step would inject a fixture, while later steps would not be able to.
67

78
7.2.0
89
----------

src/pytest_bdd/compat.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ def inject_fixture(request: FixtureRequest, arg: str, value: Any) -> None:
2424
:param arg: argument name
2525
:param value: argument value
2626
"""
27-
27+
# Ensure there's a fixture definition for the argument
2828
request._fixturemanager._register_fixture(
2929
name=arg,
3030
func=lambda: value,
3131
nodeid=request.node.nodeid,
3232
)
33+
# Note the fixture we just registered will have a lower priority
34+
# if there was already one registered, so we need to force its value
35+
# to the one we want to inject.
36+
fixture_def = request._get_active_fixturedef(arg)
37+
fixture_def.cached_result = (value, None, None)
3338

3439
else:
3540

tests/steps/test_common.py

+42
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,48 @@ def _(bar, expected_value):
7878
assert bar == "test bar"
7979

8080

81+
def test_step_function_target_fixture_redefined(pytester):
82+
pytester.makefile(
83+
".feature",
84+
target_fixture=textwrap.dedent(
85+
"""\
86+
Feature: Redefine a target fixture
87+
Scenario: Redefine the target fixture after it has been injected once in the same scenario
88+
Given there is a foo with value "test foo"
89+
Then foo should be "test foo"
90+
Given there is a foo with value "test bar"
91+
Then foo should be "test bar"
92+
"""
93+
),
94+
)
95+
pytester.makepyfile(
96+
textwrap.dedent(
97+
"""\
98+
import pytest
99+
from pytest_bdd import given, when, then, scenarios, parsers
100+
from pytest_bdd.utils import dump_obj
101+
102+
scenarios("target_fixture.feature")
103+
104+
@given(parsers.parse('there is a foo with value "{value}"'), target_fixture="foo")
105+
def _(value):
106+
return value
107+
108+
@then(parsers.parse('foo should be "{expected_value}"'))
109+
def _(foo, expected_value):
110+
dump_obj(foo)
111+
assert foo == expected_value
112+
"""
113+
)
114+
)
115+
result = pytester.runpytest("-s")
116+
result.assert_outcomes(passed=1)
117+
118+
[foo1, foo2] = collect_dumped_objects(result)
119+
assert foo1 == "test foo"
120+
assert foo2 == "test bar"
121+
122+
81123
def test_step_functions_same_parser(pytester):
82124
pytester.makefile(
83125
".feature",

0 commit comments

Comments
 (0)