From 8fe2e4ff3cffea68cbd0ed171025aace10e68e1d Mon Sep 17 00:00:00 2001 From: Alessio Bogon Date: Tue, 22 Feb 2022 16:12:54 +0100 Subject: [PATCH 1/5] Execute step definitions as if they were pytest fixture. This way we can get the same behaviour of yield-fixtures. --- pytest_bdd/scenario.py | 7 +++--- tests/feature/test_steps.py | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/pytest_bdd/scenario.py b/pytest_bdd/scenario.py index 43aacd6a..38ad4033 100644 --- a/pytest_bdd/scenario.py +++ b/pytest_bdd/scenario.py @@ -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 @@ -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) diff --git a/tests/feature/test_steps.py b/tests/feature/test_steps.py index 63ed1498..1cb72b58 100644 --- a/tests/feature/test_steps.py +++ b/tests/feature/test_steps.py @@ -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...*", + ] + ) From 421f87a605d3ebd2d4f57639bbeac24e5a82268f Mon Sep 17 00:00:00 2001 From: Alessio Bogon Date: Tue, 22 Feb 2022 16:26:23 +0100 Subject: [PATCH 2/5] Test against pytest 7.0 and python 3.10 --- .github/workflows/main.yml | 2 +- tox.ini | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7692fd91..56d11f43 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", 3.10.0-rc.2] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] steps: - uses: actions/checkout@v2 diff --git a/tox.ini b/tox.ini index 219b1cbb..070e90cc 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] distshare = {homedir}/.tox/distshare envlist = py38-pytestlatest-linters, - py39-pytest{43,44,45,46,50,51,52,53,54,60,61,62, latest}-coverage, + py39-pytest{43,44,45,46,50,51,52,53,54,60,61,62,70,latest}-coverage, py{36,37,38,310}-pytestlatest-coverage, py39-pytestlatest-xdist-coverage skip_missing_interpreters = true @@ -12,6 +12,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 From e48f6aa686568c36cdc6eac772192a39e1de513d Mon Sep 17 00:00:00 2001 From: Alessio Bogon Date: Tue, 22 Feb 2022 16:32:15 +0100 Subject: [PATCH 3/5] Update black version --- .pre-commit-config.yaml | 1 + tox.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 54eec99d..e2590a91 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,6 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/psf/black + # If you update the version here, also update it in tox.ini (py*-pytestlatest-linters) rev: 21.12b0 hooks: - id: black diff --git a/tox.ini b/tox.ini index 070e90cc..63b147e2 100644 --- a/tox.ini +++ b/tox.ini @@ -33,7 +33,7 @@ commands = {env:_PYTEST_CMD:pytest} {env:_PYTEST_MORE_ARGS:} {posargs:-vvl} ; Black doesn't support >py38 now [testenv:py38-pytestlatest-linters] -deps = black +deps = black==21.12b0 commands = black --check --verbose setup.py docs pytest_bdd tests [gh-actions] From eedfe5899e80c0201886d31bbbb22f916ac713c1 Mon Sep 17 00:00:00 2001 From: Alessio Bogon Date: Tue, 22 Feb 2022 16:37:37 +0100 Subject: [PATCH 4/5] Add changelog entry --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 661a8058..6334a09d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,7 @@ This release introduces breaking changes in order to be more in line with the of - Removed feature level examples for the gherkin compatibility (olegpidsadnyi) - Removed vertical examples for the gherkin compatibility (olegpidsadnyi) - Step arguments are no longer fixtures (olegpidsadnyi) +- 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) From 512fd0f6903ea38655684a6c8c11611b991d882c Mon Sep 17 00:00:00 2001 From: Alessio Bogon Date: Thu, 24 Feb 2022 12:45:07 +0100 Subject: [PATCH 5/5] Update pre-commit config --- .pre-commit-config.yaml | 6 +++--- pytest_bdd/cucumber_json.py | 2 +- tox.ini | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e2590a91..c2ae6050 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ repos: - repo: https://github.com/psf/black # If you update the version here, also update it in tox.ini (py*-pytestlatest-linters) - rev: 21.12b0 + rev: 22.1.0 hooks: - id: black - repo: https://github.com/pycqa/isort @@ -19,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] diff --git a/pytest_bdd/cucumber_json.py b/pytest_bdd/cucumber_json.py index 07b5e6ea..3102a503 100644 --- a/pytest_bdd/cucumber_json.py +++ b/pytest_bdd/cucumber_json.py @@ -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): diff --git a/tox.ini b/tox.ini index 8249b8c4..25fe0e2e 100644 --- a/tox.ini +++ b/tox.ini @@ -30,9 +30,8 @@ deps = -r{toxinidir}/requirements-testing.txt commands = {env:_PYTEST_CMD:pytest} {env:_PYTEST_MORE_ARGS:} {posargs:-vvl} -; Black doesn't support >py38 now [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]