KBNanda
KBNanda

Reputation: 667

How to run a specific function at the end of a specific scenario test in pytest BDD using fixtures

Background I need to run some specific method after a scenario run for a specific test scenario

What I tried

Scenario is as below

Scenario: Test Fixture
    Given I am a mechanic
    When I start a car
    Then I should get to know the primitive issues

Step definition looked as below

@pytest.mark.usefixtures("stop_car")
@scenario('../FeatureFiles/Test.feature', 'Test Fixture')
def test_mechanic():
    logging.info('Test Mechanic')


@given("I am a mechanic")
def given_mechanic():
    print('given_mechanic')


@when("I start a car")
def when_mechanic():
    print('when_mechanic')


@then("I should get to know the primitive issues")
def then_mechanic():
    print('then_mechanic')
    assert 1 < 0, 'Failed validation'


@pytest.fixture
def stop_car():
    print('stop car')

Issue Faced

The problem here is the 'stop_car()' function is triggered before the execution of the scenario. I need to run at the end of the scenario. Even if any assertion failed in Given, When or Then the method 'stop_car()' should be executed in any case

Upvotes: 1

Views: 906

Answers (3)

Wyrmwood
Wyrmwood

Reputation: 3609

This is a late answer, but to help folks who find this today - while the other answers are ways to accomplish this, it should be pointed out,

How to run a specific function at the end of a specific scenario test in pytest BDD [using fixtures]

You don't actually need a hook or fixture for this specific case since,


from pytest_bdd import scenario, given, when, then

@scenario('publish_article.feature', 'Publishing the article')
def test_publish(browser):
    assert article.title in browser.html # this is executed after the test. 

For reference

Upvotes: 0

Cynic
Cynic

Reputation: 7276

In conftest.py

def stop_car():
    print('stop car')


# After step passed or skipping hook
def pytest_bdd_after_step(request, feature, scenario, step, step_func, step_func_args):
    if 'stop-car' in scenario.tags:
        stop_car()

# After step failed hook
def pytest_bdd_step_error(request, feature, scenario, step, step_func, step_func_args, exception):
    if 'stop-car' in scenario.tags:
        stop_car()

And then in your feature file:

Feature: Car does stuff

    @stop-car
    Scenario: Test Fixture
        Given I am a mechanic
        When I start a car
        Then I should get to know the primitive issues

See pytest-bdd hooks docs for more details

Also while I'm here, if you need a before and after feature hook they use pytest modules.

# Before and After Feature Hooks
@pytest.fixture(autouse=True)
def after_feature_teardown(request):
    print("\nBefore Feature Hook...\n")
    yield True
    print("\nAfter Feature Hook...\n")
    if request.node.get_closest_marker("stop-car") is not None:
        stop_car()

Upvotes: 1

webduvet
webduvet

Reputation: 4292

Any required fixture is run ahead of the test when it's required. Think about it as something which needs to be run (fixed) before the test and in the test you use the result of that. If you do not need the result you can just yield the control to main script. Once that part is finished the rest of the function is run.

@pytest.fixture
def stop_car():
    print('this runs before scenario')
    yield
    print('stop car')

here is the relevant documentation

Upvotes: 0

Related Questions