Assume I have a scenario similar to this:
Scenario Outline: Example scenario
Given the subprocess is running
When I generate the input
And I add <argument1> to the input
And I add <argument2> to the input
And this input is passed to the subprocess
Then the output should match the <output> for <argument1> and <argument2>
I'd very much like to reuse the 'when' step as, e.g. And I add <argument> to the input
, but don't want to use an Examples table as I wish the fixtures to by dynamically generated in the step definition/conftest file. I'm currently using @pytest.mark.parametrize
to parametrize the scenario outlines like so:
import pytest
from pytest_bdd import scenario
from functools import partial
from some_lib import test_data, utils
@pytest.fixture(scope='module')
def context():
return {}
scenario = partial(scenario, '../features/example.feature')
@pytest.mark.parametrize(
[argument1, argument2],
[(test_data.TEST_ARGUMENT[1], test_data.TEST_ARGUMENT[2]),],
)
@scenario('Example scenario')
def test_example_scenario(context, argument1, argument2):
pass
I would like to be able to reuse the same step definition in the same scenario with the different arguments somehow, e.g.
@when('I add <argument> to the input')
def add_argument(context, argument):
context['input'] = utils.add_argument(context['input'], argument)
rather than having to have two step definitions, e.g.
@when('I add <argument1> to the input')
def add_argument(context, argument1):
context['input'] = utils.add_argument(context['input'], argument1)
@when('I add <argument2> to the input')
def add_argument(context, argument2):
context['input'] = utils.add_argument(context['input'], argument2)
The pytest-bdd documentation seems to suggest this is possible, but I can't quite wrap my head around how I might accomplish this without using example tables.
Often it’s possible to reuse steps giving them a parameter(s). This allows to have single implementation and multiple use, so less code. Also opens the possibility to use same step twice in single scenario and with different arguments! [sic] (Emphasis my own)
Does anyone have any ideas on how I might accomplish this?
Thank you for your time as always!
I think the pytest-bdd
documentation is rather suggesting re-usage of a step due to a variable in the step definition instead of a hard-coded value...so I think the documentation does not give you any solution for your problem.
Anyway, there is a solution that I use, which is getting the value of the step variable dynamically. Pytest-bdd
will create a pytest-fixture
for every variable you define in your steps and therefore you can obtain the value of a fixture by calling request.getfixturevalue(name_of_fixture)
, as long as you know the name of the fixture.
For your case I would use parsers.parse()
for the step definitions, so that the variables argument1
and argument2
will hold the name of the fixtures instead of their value.
@when(parsers.parse('I add {argument1} to the input'))
def add_argument(request, context, argument1):
# Remove angle brackets, because they are not part of the fixture name
argument1 = argument1.replace('<', '').replace('>', '')
argument_value = request.getfixturevalue(argument1)
context['input'] = utils.add_argument(context['input'], argument_value)