如何在相同的场景中使用相同的步骤,但在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,但不想使用Examples表,因为我希望fixture在步骤定义/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文档似乎表明这是可能的,但如果不使用示例表,我无法完全理解如何实现这一点。

通常可以重用给它们一个参数的步骤。这允许有单一的实现和多个用途,因此代码更少还可以在单个场景中使用相同的步骤两次,并使用不同的参数[sic](强调我自己(

有人知道我该如何做到这一点吗?

一如既往地感谢您抽出时间!

我认为pytest-bdd文档建议由于步骤定义中的变量而不是硬编码值而重新使用步骤。。。所以我认为文档并没有为您的问题提供任何解决方案。

无论如何,我使用了一种解决方案,即动态地获取step变量的值。Pytest-bdd将为您在步骤中定义的每个变量创建一个pytest-fixture,因此您可以通过调用request.getfixturevalue(name_of_fixture)获得fixture的值,只要您知道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)

最新更新