Feature: Gherkin steps bounding to steps definitions¶
Scenario: Steps are executed by corresponding step keyword decorator¶
Given File “steps.feature” with content:
Feature: Steps are executed by corresponding step keyword decorator Scenario: Step execution definitions are pytest fixtures by their nature and are stored at pytest "conftest.py" files (or any other place where pytest fixtures could be placed) * Step is executed by plain step decorator Given Step is executed by given step decorator When Step is executed by when step decorator Then Step is executed by then step decorator Then there are passed steps by kind: |step|given|when|then| | 1| 1| 1| 1|
And File “conftest.py” with content:
from pytest_bdd import given, when, then, step from pytest import fixture # pytest fixtures could be used from step definitions, so some # test preconditions could be stored on the pytest level @fixture def step_counter(): yield {'step': 0, 'given': 0,'when': 0,'then': 0,} # Step with any kind of keyword could be bounded # to step decorated with "step" definition @step('Step is executed by plain step decorator') def plain_step(step_counter): step_counter['step'] += 1 # Step with "Given" keyword could be bounded # to step decorated with "given" definition @given('Step is executed by given step decorator') def given_step(step_counter): step_counter['given'] += 1 # Same as "given" @when('Step is executed by when step decorator') def when_step(step_counter): step_counter['when'] += 1 # Same as "given" @then('Step is executed by then step decorator') def then_step(step_counter): step_counter['then'] += 1 @then('there are passed steps by kind:') def check_step_counter(step, step_counter): # Step datatables data could be accessed in the next manner step_data_table = step.data_table oracle_results_header = [cell.value for cell in step_data_table.rows[0].cells] oracle_results_values = [int(cell.value) for cell in step_data_table.rows[1].cells] oracle_result = dict(zip(oracle_results_header, oracle_results_values)) assert oracle_result == step_counter
When run pytest
Then pytest outcome must contain tests with statuses:
passed
1
Scenario: Steps could be executed by aliased step keyword decorator¶
It Could be useful to declare the same fixtures or steps with different names for better readability. To use the same step function with multiple step names, decorate it multiple times.
Given File “steps.feature” with content:
Feature: Steps could be executed by aliased step keyword decorator Scenario: Given Step counter * Step is executed by aliased step decorator Given Step is executed by aliased step decorator When Step is executed by aliased step decorator Then Step is executed by aliased step decorator Then there are "4" passed aliased steps
And File “conftest.py” with content:
from pytest_bdd import given, when, then, step @given('Step counter', target_fixture='step_counter') def step_counter(): yield {'steps_count': 0} @step('Step is executed by aliased step decorator') @given('Step is executed by aliased step decorator') @when('Step is executed by aliased step decorator') @then('Step is executed by aliased step decorator') def aliased_step(step_counter): step_counter['steps_count'] += 1 @then( 'there are "{int}" passed aliased steps', anonymous_group_names=('oracle_steps',), ) def then_step(step_counter, oracle_steps): assert step_counter['steps_count'] == oracle_steps
When run pytest
Then pytest outcome must contain tests with statuses:
passed
1
Rule: Steps could be executed by liberal step keyword decorator¶
Step definition decorator could be “liberal”, so it could be bound to any kind of keyword.
Background:
Given File “steps.feature” with content:
Feature: Steps could be executed by liberal step keyword decorator Scenario: Given Step counter * Step is executed by liberal step decorator Given Step is executed by liberal step decorator When Step is executed by liberal step decorator Then Step is executed by liberal step decorator * Step is executed by liberal given decorator Given Step is executed by liberal given decorator When Step is executed by liberal given decorator Then Step is executed by liberal given decorator * Step is executed by liberal when decorator Given Step is executed by liberal when decorator When Step is executed by liberal when decorator Then Step is executed by liberal when decorator * Step is executed by liberal then decorator Given Step is executed by liberal then decorator When Step is executed by liberal then decorator Then Step is executed by liberal then decorator Then there are "16" passed liberal steps
Scenario: Same step is used with different keywords
Given File “conftest.py” with content:
from pytest_bdd import given, when, then, step @given('Step counter', target_fixture='step_counter') def step_counter(): yield {'steps_count': 0} @step('Step is executed by liberal step decorator', liberal=True) @given('Step is executed by liberal given decorator', liberal=True) @when('Step is executed by liberal when decorator', liberal=True) @then('Step is executed by liberal then decorator', liberal=True) def liberal_step(step_counter): step_counter['steps_count'] += 1 @then( 'there are "{int}" passed liberal steps', anonymous_group_names=('oracle_steps',), ) def then_step(step_counter, oracle_steps): assert step_counter['steps_count'] == oracle_steps
When run pytest
Then pytest outcome must contain tests with statuses:
passed
1
Scenario: Keyworded steps could be treated as liberal by pytest command line option
Given File “conftest.py” with content:
from pytest_bdd import given, when, then, step @given('Step counter', target_fixture='step_counter') def step_counter(): yield {'steps_count': 0} @step('Step is executed by liberal step decorator') @given('Step is executed by liberal given decorator') @when('Step is executed by liberal when decorator') @then('Step is executed by liberal then decorator') def liberal_step(step_counter): step_counter['steps_count'] += 1 @then( 'there are "{int}" passed liberal steps', anonymous_group_names=('oracle_steps',), ) def then_step(step_counter, oracle_steps): assert step_counter['steps_count'] == oracle_steps
When run pytest
cli_args
–liberal-steps
Then pytest outcome must contain tests with statuses:
passed
failed
1
0