Skip to content

Commit

Permalink
Merge pull request #503 from pytest-dev/step-def-yield
Browse files Browse the repository at this point in the history
Allow "yield" in step definitions
  • Loading branch information
youtux committed Feb 24, 2022
2 parents 385e6c9 + 512fd0f commit d4f74d2
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 8 deletions.
7 changes: 4 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/psf/black
rev: 21.12b0
# If you update the version here, also update it in tox.ini (py*-pytestlatest-linters)
rev: 22.1.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
Expand All @@ -18,7 +19,7 @@ repos:
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/asottile/pyupgrade
rev: v2.29.1
rev: v2.31.0
hooks:
- id: pyupgrade
args: [--py36-plus]
args: [--py37-plus]
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This release introduces breaking changes in order to be more in line with the of
- Removed vertical examples for the gherkin compatibility (olegpidsadnyi)
- Step arguments are no longer fixtures (olegpidsadnyi)
- Drop support of python 3.6, pytest 4 (elchupanebrej)
- Step definitions can have "yield" statements again (4.0 release broke it). They will be executed as normal fixtures: code after the yield is executed during teardown of the test. (youtux)



Expand Down
2 changes: 1 addition & 1 deletion pytest_bdd/cucumber_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def _get_result(self, step, report, error_message=False):
result = {"status": "failed", "error_message": str(report.longrepr) if error_message else ""}
elif report.skipped:
result = {"status": "skipped"}
result["duration"] = int(math.floor((10 ** 9) * step["duration"])) # nanosec
result["duration"] = int(math.floor((10**9) * step["duration"])) # nanosec
return result

def _serialize_tags(self, item):
Expand Down
7 changes: 4 additions & 3 deletions pytest_bdd/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import typing

import pytest
from _pytest.fixtures import FixtureLookupError
from _pytest.fixtures import FixtureLookupError, call_fixture_func

from . import exceptions
from .feature import get_feature, get_features
Expand Down Expand Up @@ -112,8 +112,9 @@ def _execute_step_function(request, scenario, step, step_func):

request.config.hook.pytest_bdd_before_step_call(**kw)
target_fixture = getattr(step_func, "target_fixture", None)
# Execute the step.
return_value = step_func(**kwargs)

# Execute the step as if it was a pytest fixture, so that we can allow "yield" statements in it
return_value = call_fixture_func(fixturefunc=step_func, request=request, kwargs=kwargs)
if target_fixture:
inject_fixture(request, target_fixture, return_value)

Expand Down
48 changes: 48 additions & 0 deletions tests/feature/test_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,51 @@ def test_when_step_validation_error():
result.assert_outcomes(failed=1)
result.stdout.fnmatch_lines(["*test_when_step_validation_error*FAILED"])
assert "INTERNALERROR" not in result.stdout.str()


def test_steps_with_yield(testdir):
"""Test that steps definition containing a yield statement work the same way as
pytest fixture do, that is the code after the yield is executed during teardown."""

testdir.makefile(
".feature",
a="""\
Feature: A feature
Scenario: A scenario
When I setup stuff
Then stuff should be 42
""",
)
testdir.makepyfile(
textwrap.dedent(
"""\
import pytest
from pytest_bdd import given, when, then, scenarios
scenarios("a.feature")
@when("I setup stuff", target_fixture="stuff")
def stuff():
print("Setting up...")
yield 42
print("Tearing down...")
@then("stuff should be 42")
def check_stuff(stuff):
assert stuff == 42
print("Asserted stuff is 42")
"""
)
)
result = testdir.runpytest("-s")
result.assert_outcomes(passed=1)
result.stdout.fnmatch_lines(
[
"*Setting up...*",
"*Asserted stuff is 42*",
"*Tearing down...*",
]
)
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ setenv =
xdist: _PYTEST_MORE_ARGS=-n3 -rfsxX
deps =
pytestlatest: pytest
pytest70: pytest~=7.0.0
pytest62: pytest~=6.2.0
pytest61: pytest~=6.1.0
pytest60: pytest~=6.0.0
Expand All @@ -30,7 +31,7 @@ deps =
commands = {env:_PYTEST_CMD:pytest} {env:_PYTEST_MORE_ARGS:} {posargs:-vvl}

[testenv:py310-pytestlatest-linters]
deps = black==21.12b0
deps = black==22.1.0
commands = black --check --verbose setup.py docs pytest_bdd tests

[gh-actions]
Expand Down

0 comments on commit d4f74d2

Please sign in to comment.