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

Show pass/fail per step in Gherkin terminal reporter #456

Open titouanc opened 3 years ago

titouanc commented 3 years ago

Improve the Gherkin Terminal Reporter so that it shows the pass/fail status per step. This is particularly useful when the same step definition is used several times in the same scenario. In such a case, the pytest traceback is not particularly useful to know which invocation of the step failed, so adding an indication in the Gherkin report provides useful insights.

This is illustrated in the visuals below, where we could clearly see which invocation of Then I have an apple in the bag yielded the error, while the pytest traceback doesn't provide this information:

2021-10-27-145708_933x291_scrot 2021-10-27-150251_933x532_scrot 2021-10-27-150416_977x1005_scrot 2021-10-27-150506_978x1006_scrot

Here is sample code for the above:

Feature: Bag
    Scenario: Having a bag
        Given that I have an empty bag
        Then the bag is empty

    Scenario: Adding things in a bag
        Given that I have an empty bag

        When I add an apple in the bag
        Then I have an apple in the bag

        When I add a banana in the bag
        Then I have an apple in the bag
        And I have a banana in the bag

        When I remove a banana from the bag
        Then I have an apple in the bag

        When I remove an apple from the bag
        Then the bag is empty
from os import environ

import pytest
from pytest_bdd import (
    given,
    scenarios,
    then,
    when,
    parsers,
)

scenarios('bag.feature')

@pytest.fixture
def bag():
    return set()

@given('that I have an empty bag')
def i_have_an_empty_bag(bag):
    pass

@when(parsers.re(r'I add an? (?P<item>\w+) in the bag'))
def i_add_an_item_in_the_bag(bag, item):
    if 'BUG1' in environ:
        bag.clear()
    bag.add(item)

@when(parsers.re(r'I remove an? (?P<item>\w+) from the bag'))
def i_remove_an_item_from_the_bag(bag, item):
    bag.remove(item)
    if 'BUG2' in environ:
        bag.clear()

@then(parsers.re(r'I have an? (?P<item>\w+) in the bag'))
def i_have_an_item_in_the_bag(bag, item):
    assert item in bag

@then('the bag is empty')
def the_bag_is_empty(bag):
    assert len(bag) == 0
titouanc commented 2 years ago

Hello @olegpidsadnyi !

I just wanted to check if you're interested in merging this at some point, or if I should simply close the PR ?

elchupanebrej commented 2 years ago

@youtux