我如何在同一场景中使用相同的步骤,但在 pytest-bdd 中使用不同的参数?

How might I use the same step in the same scenario, but with different parameters in pytest-bdd?

假设我有一个类似的场景:

    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>

我非常想重用 'when' 步骤,例如And I add <argument> to the input,但不想使用示例 table,因为我希望在步骤 definition/conftest 文件中动态生成固定装置。我目前正在使用 @pytest.mark.parametrize 来参数化场景大纲,如下所示:

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

我希望能够以某种方式在具有不同参数的同一场景中重用相同的步骤定义,例如

@when('I add <argument> to the input')
def add_argument(context, argument):
    context['input'] = utils.add_argument(context['input'], argument)

而不是必须有两个步骤定义,例如

@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)

pytest-bdd documentation 似乎暗示这是可能的,但我无法完全理解如果不使用示例 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)

有人对我如何完成这个有任何想法吗?

一如既往地感谢您的宝贵时间!

我认为 pytest-bdd 文档更倾向于建议重新使用步骤,因为步骤定义中的变量而不是硬编码值...所以我认为文档没有给你您的问题的任何解决方案。

无论如何,有一个我使用的解决方案,它是动态获取 step 变量的值。 Pytest-bdd 将为您在步骤中定义的每个变量创建一个 pytest-fixture,因此只要您知道夹具的名称,就可以通过调用 request.getfixturevalue(name_of_fixture) 来获取夹具的值。

对于你的情况,我将使用 parsers.parse() 作为步骤定义,这样变量 argument1argument2 将保存灯具的名称而不是它们的值。

例子

@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)