pytest-bdd icon indicating copy to clipboard operation
pytest-bdd copied to clipboard

Rewrite pytest-bdd to use hooks and marks

Open youtux opened this issue 6 years ago • 8 comments

Following the suggestion from issue #296, I will try to re-implement pytest-bdd to use marks and hooks.

I imagine an API that will look like this:

# test_some_scenario.py
pytestmark = pytest.mark.scenarios('a.feature')

# override "Scenario 3"
@pytest.mark.scenario('a.feature', 'Scenario 3')
def test_a_scenario(...):
    # do something more
    pass

instead of the current way:

import pytest_bdd

# override "Scenario 3"
@pytest_bdd.scenario('a.feature', 'Scenario 3')
def test_a_scenario(...):
    # do something more
    pass

scenarios('a.feature')

I yet don't know if this is entirely feasible without breaking other features, but we will see.

Short note about @scenario(...)

Potentially, I will also remove the single scenario mark/decorator, given that the only thing it allows to do is to require some more fixtures before the scenario is run, and to execute some more logic after the scenario finished. This custom logic can already be implemented using given and then steps, but I understand that sometimes it can be just some compensation logic that should not appear in the feature file. I still didn't figure out what to do with this, so probably I'll keep the @scenario mark/decorator for the time being.

@bubenkoff @olegpidsadnyi @sliwinski-milosz: Feedback on this idea would be appreciated.

youtux avatar Jul 10 '19 08:07 youtux

I use @scenario to run things after the test. For example I reset my env to pristine condition when I run some destructive tests. Edit: I did not know @scenario can override@scenarios

Vic152 avatar Jul 22 '19 13:07 Vic152

@Vic152 @Vic152 fair enough, but I would intend to still support running pre-test and post-test actions by using fixtures instead. So potentially your code would transform from this:

@scenario('a.feature', 'A scenario')
def test_a_scenario():
    do_cleanup()

to this:

pytestmark = [
    pytest.mark.scenarios('a.feature'),
    pytest.mark.usefixtures('cleanup_fixture'),
]

@pytest.fixture
def cleanup_fixture():
    yield
    do_cleanup()  # This would be run at the the end of each test

youtux avatar Jul 22 '19 13:07 youtux

@youtux What about if I wanted to use the cleanup fixture only in one scenario in the entire feature file? (I was trying to read pytest docs but the page seems to be down)

Vic152 avatar Jul 22 '19 14:07 Vic152

@youtux please review ideas from https://github.com/elchupanebrej/pytest-bdd/pull/33 , they could be a good basement for this feature.

  • feature/scenario registry could be saved in a module-scoped fixture
  • parametrization could be done from pytest_generate_tests hook

elchupanebrej avatar Apr 20 '22 15:04 elchupanebrej

Also, we could auto-collect Feature files using https://docs.pytest.org/en/7.1.x/example/nonpython.html ideas. For example how this could be: all steps are defined at conftest.py plugins and feature files are placed in the same directory.

elchupanebrej avatar Jul 24 '22 00:07 elchupanebrej

For example how this could be: all steps are defined at conftest.py plugins and feature files are placed in the same directory.

Yes, I wanted to do that for quite some time already, but never had the time to dig into that.

youtux avatar Jul 24 '22 17:07 youtux

I'll try to implement PoC fo auto import in the nearest future

elchupanebrej avatar Jul 24 '22 21:07 elchupanebrej

@youtux please check the approach from https://github.com/elchupanebrej/pytest-bdd-ng/pull/74 and share your thoughts. That PR also uses ideas from #342 #542

elchupanebrej avatar Oct 06 '22 17:10 elchupanebrej