Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix step fixture injection with multiple steps #700

Merged
merged 1 commit into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Changelog

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

7.2.0
----------
Expand Down
7 changes: 6 additions & 1 deletion src/pytest_bdd/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ def inject_fixture(request: FixtureRequest, arg: str, value: Any) -> None:
:param arg: argument name
:param value: argument value
"""

# Ensure there's a fixture definition for the argument
request._fixturemanager._register_fixture(
name=arg,
func=lambda: value,
nodeid=request.node.nodeid,
)
# Note the fixture we just registered will have a lower priority
# if there was already one registered, so we need to force its value
# to the one we want to inject.
fixture_def = request._get_active_fixturedef(arg)
fixture_def.cached_result = (value, None, None)

else:

Expand Down
42 changes: 42 additions & 0 deletions tests/steps/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,48 @@ def _(bar, expected_value):
assert bar == "test bar"


def test_step_function_target_fixture_redefined(pytester):
pytester.makefile(
".feature",
target_fixture=textwrap.dedent(
"""\
Feature: Redefine a target fixture
Scenario: Redefine the target fixture after it has been injected once in the same scenario
Given there is a foo with value "test foo"
Then foo should be "test foo"
Given there is a foo with value "test bar"
Then foo should be "test bar"
"""
),
)
pytester.makepyfile(
textwrap.dedent(
"""\
import pytest
from pytest_bdd import given, when, then, scenarios, parsers
from pytest_bdd.utils import dump_obj

scenarios("target_fixture.feature")

@given(parsers.parse('there is a foo with value "{value}"'), target_fixture="foo")
def _(value):
return value

@then(parsers.parse('foo should be "{expected_value}"'))
def _(foo, expected_value):
dump_obj(foo)
assert foo == expected_value
"""
)
)
result = pytester.runpytest("-s")
result.assert_outcomes(passed=1)

[foo1, foo2] = collect_dumped_objects(result)
assert foo1 == "test foo"
assert foo2 == "test bar"


def test_step_functions_same_parser(pytester):
pytester.makefile(
".feature",
Expand Down
Loading