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

Parsed step aliases no longer working on 6.0.0 #528

Closed
kimsappi opened this issue Jul 5, 2022 · 7 comments · Fixed by #530
Closed

Parsed step aliases no longer working on 6.0.0 #528

kimsappi opened this issue Jul 5, 2022 · 7 comments · Fixed by #530
Assignees
Labels

Comments

@kimsappi
Copy link

kimsappi commented Jul 5, 2022

Having multiple step aliases with parsing is no longer supported as of pytest-bdd 6.0.0. The error is reproducible by varying the order of the decorators (@given(...) in the following example): only the top-most decorator ever works.

Example:

Input:

$ cat x.feature 
Feature: x

    Scenario: x
        Given I have a "parameterised" step

        Then success

    Scenario: y
        Given I have a differently "parameterised" step

        Then success

$ cat test_x.py 
from pytest_bdd import scenario, given, then, parsers

@scenario('x.feature', 'x')
def test_x():
    pass

@scenario('x.feature', 'y')
def test_y():
    pass

@given(parsers.parse('I have a "{param}" step'))
@given(parsers.parse('I have a differently "{param}" step'))
def parameterised(param):
    pass

@then('success')
def success():
    assert True

Expected output (pytest-bdd==5.0.0):

$ py.test
===================================== test session starts =====================================
platform linux -- Python 3.9.2, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/xxx/pytestbdd
plugins: bdd-5.0.0
collected 2 items                                                                             

test_x.py ..                                                                            [100%]

====================================== 2 passed in 0.04s ======================================

Real output (pytest-bdd==6.0.0):

$ py.test
===================================== test session starts =====================================
platform linux -- Python 3.9.2, pytest-7.1.2, pluggy-1.0.0
rootdir: /home/xxx/pytestbdd
plugins: bdd-6.0.0
collected 2 items                                                                             

test_x.py .F                                                                            [100%]

========================================== FAILURES ===========================================
___________________________________________ test_y ____________________________________________

request = <FixtureRequest for <Function test_y>>, _pytest_bdd_example = {}

    @pytest.mark.usefixtures(*func_args)
    def scenario_wrapper(request: FixtureRequest, _pytest_bdd_example: dict[str, str]) -> Any:
        scenario = templated_scenario.render(_pytest_bdd_example)
>       _execute_scenario(feature, scenario, request)

venv/lib/python3.9/site-packages/pytest_bdd/scenario.py:184: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.9/site-packages/pytest_bdd/scenario.py:154: in _execute_scenario
    _execute_step_function(request, scenario, step, step_func)
venv/lib/python3.9/site-packages/pytest_bdd/scenario.py:112: in _execute_step_function
    for arg, value in parser.parse_arguments(step.name).items():
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <pytest_bdd.parsers.parse object at 0x7f7290892460>
name = 'I have a differently "parameterised" step'

    def parse_arguments(self, name: str) -> dict[str, Any]:
        """Get step arguments.
    
        :return: `dict` of step arguments
        """
>       return cast(Dict[str, Any], self.parser.parse(name).named)
E       AttributeError: 'NoneType' object has no attribute 'named'

venv/lib/python3.9/site-packages/pytest_bdd/parsers.py:68: AttributeError
=================================== short test summary info ===================================
FAILED test_x.py::test_y - AttributeError: 'NoneType' object has no attribute 'named'
================================= 1 failed, 1 passed in 0.10s =================================

Environment

$ pip freeze
attrs==21.4.0
glob2==0.7
iniconfig==1.1.1
Mako==1.2.1
MarkupSafe==2.1.1
packaging==21.3
parse==1.19.0
parse-type==0.6.0
pluggy==1.0.0
py==1.11.0
pyparsing==3.0.9
pytest==7.1.2
pytest-bdd==6.0.0
six==1.16.0
tomli==2.0.1

$ diff <(pip freeze) 5.0.0
13c13
< pytest-bdd==6.0.0
---
> pytest-bdd==5.0.0

$ python3 --version
Python 3.9.2
@youtux youtux added the bug label Jul 5, 2022
@youtux youtux self-assigned this Jul 5, 2022
@dcendents
Copy link
Contributor

I also saw the same error but in my case I have both a @given and a @when step on the same function in that order (@given declared first and @when second). I believe both steps are registered but only the first parser is ever used.

e.g.: In my test the @when step gets executed but the string is parsed using the statement from the @given parser which does not match and then returns None here:

    def parse(self, string, evaluate_result=True):
        """Match my format to the string exactly.

        Return a Result or Match instance or None if there's no match.
        """
        m = self._match_re.match(string)
        if m is None:
            return None

So my test fails with the following error:

    def parse_arguments(self, name: str) -> dict[str, Any]:
        """Get step arguments.
    
        :return: `dict` of step arguments
        """
>       return cast(Dict[str, Any], self.parser.parse(name).named)
E       AttributeError: 'NoneType' object has no attribute 'named'

@youtux
Copy link
Contributor

youtux commented Jul 6, 2022

I made a fix in #530, can you try it out before I make a release to check if it fixes it for your project?

You can install it using:

pip install git+https://github.com/pytest-dev/pytest-bdd.git@15e1a8aa201384e9cd7d026af0200f5942b2cadd#egg=pytest-bdd

@dcendents
Copy link
Contributor

@youtux yes it is working for me (my project has 1267 tests)

I only had to convert some scenarios where I used vertical example tables which is not supported anymore, otherwise upgrading from 5.0.0 to this fixed version works.

@kimsappi
Copy link
Author

kimsappi commented Jul 6, 2022

Thank you for the swift work. Tested it against some of our projects, and they work with this version.

@youtux
Copy link
Contributor

youtux commented Jul 6, 2022

Thanks for testing, I'll probably release 6.0.1 tomorrow.

@youtux
Copy link
Contributor

youtux commented Jul 7, 2022

Version 6.0.1 is out.

@tiborsimon
Copy link

It seems like you only created a tag here in Github, but the latest release is still 6.0.0. On Pypi it was updated, and the latest version is 6.0.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants