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

Pytest-BDD parse matcher step definitions #205

Open
neskk opened this issue Apr 22, 2024 · 8 comments · May be fixed by #206
Open

Pytest-BDD parse matcher step definitions #205

neskk opened this issue Apr 22, 2024 · 8 comments · May be fixed by #206
Labels
python ⚡ enhancement Request for new functionality

Comments

@neskk
Copy link

neskk commented Apr 22, 2024

👓 What did you see?

I've configured the cucumber plugin to look for step defs in the right paths, but it's not matching the step-defs.

    "cucumber.features": [
        "**/tests/**/*.feature",
    ],
    "cucumber.glue": [
        "**/step_defs/**/*.py"
    ],

It finds and parses the files but does not recognize the step-defs:

[Info  - 10:45:53 PM] * Found 7 feature file(s) in ["src/test/**/*.feature","features/**/*.feature","tests/**/*.feature","*specs*/**/*.feature","**/tests/**/*.feature"]
[Info  - 10:45:53 PM] * Found 74 steps in those feature files
[Info  - 10:45:54 PM] * Found 26 glue file(s) in ["**/step_defs/**/*.py"]
[Info  - 10:45:54 PM] * Found 0 parameter types in those glue files
[Info  - 10:45:54 PM] * Found 0 step definitions in those glue files
[Info  - 10:45:54 PM] * Built 52 suggestions for auto complete

Example step-def:

from pytest_bdd import given, parsers, then, when

@given(parsers.parse("a stub exists with:" + os.linesep + "{stub_str}"))
@when(parsers.parse("creating a stub with:" + os.linesep + "{stub_str}"))
def creating_stub_with(
    request: pytest.FixtureRequest,
    context: handler.DynamicValuesHandler,
    mock_server: MockServerClient,
    stub_str: str,
) -> Stub:
    ...

We implemented most of the step-defs like this, using pytest_bdd parsers.
Is this "parsers" format compatible with the cucumber plugin?


Another question I have is in regards to external libraries with step definitions.
Currently at my company we're using a shared library that implements the most common step-defs we use in our tests.

Will the vscode cucumber plugin also pick these definitions as well from imports?

Thank you!

I can try to setup a full example if needed.

✅ What did you expect to see?

I expected step definitions to be recognized and be able to use the plugin tools.

📦 Which tool/library version are you using?

cucumber plugin v1.10
vscode 1.88.1

🔬 How could we reproduce it?

No response

📚 Any additional context?

No response

@kieran-ryan kieran-ryan transferred this issue from cucumber/vscode Apr 22, 2024
@kieran-ryan kieran-ryan changed the title Pytest-BDD: Step definitions not found Pytest-BDD parse matcher step definitions Apr 22, 2024
@kieran-ryan kieran-ryan added the ⚡ enhancement Request for new functionality label Apr 22, 2024
@kieran-ryan kieran-ryan changed the title Pytest-BDD parse matcher step definitions Pytest BDD parse matcher step definitions Apr 22, 2024
@kieran-ryan kieran-ryan changed the title Pytest BDD parse matcher step definitions Pytest-BDD parse matcher step definitions Apr 22, 2024
@neskk
Copy link
Author

neskk commented Apr 23, 2024

@kieran-ryan sorry to bother you again but my questions kinda remain unanswered.
I'm also sorry I didn't create this issue in the right place, as you had suggested.

  • From what I managed to understand, the step definitions syntax that utilizes pytest_bdd.parsers is not recognized, right?

  • Any thoughts on the issue of importing step-definitions from a library? It should work out of the box?

Thank you for your time.

@kieran-ryan
Copy link
Member

No worries @neskk

From what I managed to understand, the step definitions syntax that utilizes pytest_bdd.parsers is not recognized, right?

Correct. As such have listed this issue as an 'enhancement' - will need to assess effort to support and get back to you

Any thoughts on the issue of importing step-definitions from a library? It should work out of the box?

Assuming you are referring to including step definitions stored in an external library into your repository either via a submodule or a package (such as through 'pip'). If so, it should be possible by configuring the Cucumber extension or language server to point to where those step definitions are stored in order to scan them e.g. referencing inside a virtual environment could look like "venv/lib/**/shared_steps/**/*.py"

@kieran-ryan kieran-ryan linked a pull request Apr 23, 2024 that will close this issue
5 tasks
@kieran-ryan
Copy link
Member

@neskk, interesting to observe some of the design choices with pytest-bdd - I see some slight deviations with multi-lines steps compared to the gherkin parser.

With pytest-bdd:

Given a stub exists with:
  one
  two
When creating a stub with:
  | sample |

With the gherkin parser:

Given a stub exists with:
  """
  one
  two
  """
When creating a stub with:
  | sample |

With Behave, we would include only the first portion of the expression; and would access the table via the context.

@given("a stub exists with:")
def step_impl(context):
    for row in context.table:
        model.add_user(name=row['name'], department=row['department'])

This creates a challenge to handle it appropriately with pytest-bdd, as the table is included in the match itself. To support, will likely need to find a pattern that ignores the additional lines to match only the step portion.

Thinking about what would need to be matched:

  1. Is os.linestep required in your case or could \n be used instead? We scan rather than evaluate the code that's referenced. However we could ignore that portion of the expression.

  2. Can positional arguments be used with pytest-bdd instead of keyword arguments i.e. if we removed stub_str from the expression - but kept it within the function - would it still run? The reason I ask, we typically handle named parameters as a reference to a Cucumber Expressions Parameter Type - which I assume are unsupported with pytest-bdd; so it may lookup and fail; though leaving it empty will match anything. May not be important if we ignore this section for multiline steps; and we have to consider what's optimal to support pytest-bdd. The following for example would work with behave

    @given("an unnamed parameter {}")
    def step_impl(context, parameter):
        ...

@neskk
Copy link
Author

neskk commented Jul 19, 2024

@kieran-ryan hello again, I'm sorry I haven't replied sooner.

To answer your questions:

  1. os.linesep is not absolutely required, I think \n would work fine here.
  2. Regarding positional arguments, I don't think they are supported on pytest-bdd step-def parser implementation (see https://pytest-bdd.readthedocs.io/en/stable/#step-arguments).
    I ran a test similar to your example:
@given("an unnamed parameter {}")
def step_impl(context, parameter):
    ...

It fails because it tries to look for a fixture named parameter since the parameter was unnamed.

I saw you created a PR for adding support to "parse" syntax. I can try to help test it, but I'm not a much of a TypeScript coder.

@kieran-ryan
Copy link
Member

Awesome @neskk 💪

Would definitely welcome any contributions if you want to open a PR to the branch of the existing PR? A good place to start would be to get the unit tests running locally (a note you may need node v18) and to replace step definitions with their pytest-bdd equivalent and see what works or breaks. Believe had something working but can’t fully recall status
https://github.com/cucumber/language-service/blob/main/test/language/testdata/python/StepDefinitions.py

A note that the expression builder Test that reads that test data expects a specific set of step definition patterns, but you can extend that similar to what has been done with the JavaScript implementation. If you run into any issues I would be happy to help you contribute, feel free to open a draft PR early if something you want to look at and will help

...(languageName === 'javascript' ? ['a compiled format'] : []),

@neskk
Copy link
Author

neskk commented Jul 22, 2024

Thank you for the feedback.
I was referring the PR that you open, I can checkout and try to execute the unit tests.
Right now I can't spare much time to help develop this, especially because I'm not familiarized with the project. I just thought it would be great that the vs-code cucumber plugin actually supported our pytest-bdd step-defs, similarly to how PyCharm makes everything work.

@jenisys
Copy link

jenisys commented Sep 12, 2024

@kieran-ryan

Would definitely welcome any contributions if you want to open a PR to the branch of the existing PR? A good place to start would be to get the unit tests running locally (a note you may need node v18) and to replace step definitions with their pytest-bdd equivalent and see what works or breaks. Believe had something working but can’t fully recall status https://github.com/cucumber/language-service/blob/main/test/language/testdata/python/StepDefinitions.py

NOTES:

  • The StepDefinitions.py may be sufficient for testing the language-server
  • BUT: They are invalid if you want to use them with behave for example.
    In behave you need to specify which step-matcher is used by using use_step_matcher() (like: parse, cucumber_expressions, re, etc.) before you use it for a step-decorator. Otherwise, the step-registration and later use of these steps will not work.
  • pytest-bdd should have a similar problem because it wraps the step-syntax w/ a parser call.
  • AND: Python has the naming convention to use snake_case instead of CamelCase for Python modules/packages. Therefore, StepDefinitions.py should be renamed to step_definitions.py.

SEE:

@neskk
Copy link
Author

neskk commented Oct 1, 2024

@kieran-ryan I posted some questions on language-service PR#206. If you can please take a look at it.
I don't know how the guys from Jetbrains managed to support all the pytest-bdd formats, but we should be able to do it too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
python ⚡ enhancement Request for new functionality
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants