pytest-dev / pytest-bdd

BDD library for the pytest runner
https://pytest-bdd.readthedocs.io/en/latest/
MIT License
1.32k stars 221 forks source link

Cannot parse datatable with examples #741

Open sayurionishi opened 23 hours ago

sayurionishi commented 23 hours ago

Sample Scenario

Scenario Outline: User selects bookmark position
    When the user selects A in the bookmarks
    Then the position should be the following
      | x   | y   | z   |
      | <x> | <y> | <z> |
Examples:
  | x | y | z |
  | 1 | 2 | 3 |

Before, it could parse the values correctly, returning 1, 2, 3, but now it returns the placeholders as strings <x>, <y>, <z>. This worked before the recent change in data tables. Hope you could help check this issue, thank you

jsa34 commented 23 hours ago

Hello @sayurionishi

Could you please provide a full MVP?

This looks invalid gherkin syntax - there is no Feature, for example.

Could you also provide the step definitions used?

Also, you refer to datatables, but this has both examples table and datatable. Hopefully the step defs will clarify what you are trying to do: you seem to have both here, but none of the examples are actually being used in your feature file?

Try and use the bug reporting template provided when raising a bug: Describe the bug A clear and concise description of what the bug is.

To Reproduce Write a Minimal, Reproducible Example to show the bug.

Expected behavior A clear and concise description of what you expected to happen.

Additional context Add any other context about the problem here.

Version

sayurionishi commented 23 hours ago

Good day, here it is @jsa34

Feature: Bookmarks Tests
Scenario Outline: User selects bookmark position
    When the user selects A in the bookmarks
    Then the position should be the following
      | x   | y   | z   |
      | <x> | <y> | <z> |
Examples:
  | x | y | z |
  | 1 | 2 | 3 |
@then(parsers.parse("the position should be the following"))
def then_position(datatable):
    expected_position = parse_table(datatable)
    current_position = {'x': 1, 'y': 2, 'z': 3}
    assert (
        current_position["x"] == expected_position["x"]
    ), f'actual: {current_position["x"]}, expected: {expected_position["x"]}'
    assert (
        current_position["y"] == expected_position["y"]
    ), f'actual: {current_position["y"]}, expected: {expected_position["y"]}'
    assert (
        current_position["z"] == expected_position["z"]
    ), f'actual: {current_position["z"]}, expected: {expected_position["z"]}'

def parse_table(data_table):
    headers = data_table[0]
    lst = [dict(zip(headers, row)) for row in data_table[1:]]

    if len(lst) == 1:
        return lst[0]
    return lst
Error: 1 was not equal to "<x>"
E       AssertionError: actual: 1, expected: <x>
E       assert '1' == '<x>'
E
E         - <x>
E         + 1

I have also edited the first comment as it does not display the datatable properly
pytest version: 8.1.1 pytest-bdd version: 8.0.0 OS: Windows

Thank you

jsa34 commented 23 hours ago

Thanks - that's fab.

I will take a look, but I haven't seen example table values used in a data table before...

youtux commented 21 hours ago

Interesting use case, I wonder if other implementations treat data tables as part of the template, or not. Maybe to be raised with the Cucumber guys.

Sounds like a valid use case for me though, hopefully it won't be too hard to fix.

jsa34 commented 21 hours ago

Agreed - I have asked to get a conclusive idea of where example params should affect (for example, I know scenario names can use example params, too)

jsa34 commented 13 hours ago

Raised with Cucumber, and sought clarification. The following need to be interpolated with examples table: