forked from test_framework/pytest-bdd
Allow mixing feature example table with scenario example table
This commit is contained in:
parent
a54da26578
commit
24522b8fdc
|
@ -1,6 +1,11 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
2.13.1
|
||||
------
|
||||
|
||||
- Allow mixing feature example table with scenario example table (bubenkoff, olegpidsadnyi)
|
||||
|
||||
2.13.0
|
||||
------
|
||||
|
||||
|
|
32
README.rst
32
README.rst
|
@ -575,6 +575,38 @@ among all the scenarios of that feature:
|
|||
When I eat <eat> apples
|
||||
Then I should have <left> apples
|
||||
|
||||
For some more complex case, you might want to parametrize on both levels: feature and scenario.
|
||||
This is allowed as long as parameter names do not clash:
|
||||
|
||||
|
||||
..code-block:: gherkin
|
||||
Feature: Outline
|
||||
|
||||
Examples:
|
||||
| start | eat | left |
|
||||
| 12 | 5 | 7 |
|
||||
| 5 | 4 | 1 |
|
||||
|
||||
Scenario Outline: Eat fruits
|
||||
Given there are <start> <fruits>
|
||||
When I eat <eat> <fruits>
|
||||
Then I should have <left> <fruits>
|
||||
|
||||
Examples:
|
||||
| fruits |
|
||||
| oranges |
|
||||
| apples |
|
||||
|
||||
Scenario Outline: Eat vegetables
|
||||
Given there are <start> <vegetables>
|
||||
When I eat <eat> <vegetables>
|
||||
Then I should have <left> <vegetables>
|
||||
|
||||
Examples:
|
||||
| vegetables |
|
||||
| carrots |
|
||||
| tomatoes |
|
||||
|
||||
|
||||
Combine scenario outline and pytest parametrization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
from pytest_bdd.steps import given, when, then
|
||||
from pytest_bdd.scenario import scenario, scenarios
|
||||
|
||||
__version__ = '2.13.0'
|
||||
__version__ = '2.13.1'
|
||||
|
||||
__all__ = [given.__name__, when.__name__, then.__name__, scenario.__name__, scenarios.__name__]
|
||||
|
|
|
@ -446,13 +446,14 @@ class Scenario(object):
|
|||
"""
|
||||
return frozenset(sum((list(step.params) for step in self.steps), []))
|
||||
|
||||
def get_examples(self):
|
||||
def get_example_params(self):
|
||||
"""Get examples."""
|
||||
return self.examples or self.feature.examples
|
||||
return set(self.examples.example_params + self.feature.examples.example_params)
|
||||
|
||||
def get_params(self):
|
||||
"""Get example params."""
|
||||
return self.get_examples().get_params(self.example_converters)
|
||||
for examples in [self.feature.examples, self.examples]:
|
||||
yield examples.get_params(self.example_converters)
|
||||
|
||||
def validate(self):
|
||||
"""Validate the scenario.
|
||||
|
@ -460,11 +461,12 @@ class Scenario(object):
|
|||
:raises ScenarioValidationError: when scenario is not valid
|
||||
"""
|
||||
params = self.params
|
||||
if params and self.examples.example_params and params != set(self.examples.example_params):
|
||||
example_params = self.get_example_params()
|
||||
if params and example_params and params != example_params:
|
||||
raise exceptions.ScenarioExamplesNotValidError(
|
||||
"""Scenario "{0}" in the feature "{1}" has not valid examples. """
|
||||
"""Set of step parameters {2} should match set of example values {3}.""".format(
|
||||
self.name, self.feature.filename, sorted(params), sorted(self.examples.example_params),
|
||||
self.name, self.feature.filename, sorted(params), sorted(example_params),
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ def _get_scenario_decorator(feature, feature_name, scenario, scenario_name, call
|
|||
|
||||
args = inspect.getargspec(_pytestbdd_function).args
|
||||
function_args = list(args)
|
||||
for arg in scenario.get_examples().example_params:
|
||||
for arg in scenario.get_example_params():
|
||||
if arg not in function_args:
|
||||
function_args.append(arg)
|
||||
if "request" not in function_args:
|
||||
|
@ -271,9 +271,9 @@ def _get_scenario_decorator(feature, feature_name, scenario, scenario_name, call
|
|||
firstlineno=caller_function.f_lineno,
|
||||
)
|
||||
|
||||
params = scenario.get_params()
|
||||
if params:
|
||||
_scenario = pytest.mark.parametrize(*params)(_scenario)
|
||||
for param_set in scenario.get_params():
|
||||
if param_set:
|
||||
_scenario = pytest.mark.parametrize(*param_set)(_scenario)
|
||||
|
||||
for tag in scenario.tags.union(feature.tags):
|
||||
_scenario = getattr(pytest.mark, tag)(_scenario)
|
||||
|
|
|
@ -6,6 +6,11 @@ Feature: Outline
|
|||
| 5 | 4 | 1 |
|
||||
|
||||
Scenario Outline: Outlined given, when, thens
|
||||
Given there are <start> cucumbers
|
||||
When I eat <eat> cucumbers
|
||||
Then I should have <left> cucumbers
|
||||
Given there are <start> <fruits>
|
||||
When I eat <eat> <fruits>
|
||||
Then I should have <left> <fruits>
|
||||
|
||||
Examples:
|
||||
| fruits |
|
||||
| oranges |
|
||||
| apples |
|
||||
|
|
|
@ -105,11 +105,35 @@ def test_empty_example_values():
|
|||
[u'start', u'eat', u'left'], [['#', '', '']])
|
||||
|
||||
|
||||
@given('there are <start> <fruits>')
|
||||
def start_fruits(start, fruits):
|
||||
assert isinstance(start, int)
|
||||
return {fruits: dict(start=start)}
|
||||
|
||||
|
||||
@when('I eat <eat> <fruits>')
|
||||
def eat_fruits(start_fruits, eat, fruits):
|
||||
assert isinstance(eat, float)
|
||||
start_fruits[fruits]['eat'] = eat
|
||||
|
||||
|
||||
@then('I should have <left> <fruits>')
|
||||
def should_have_left_fruits(start_fruits, start, eat, left, fruits):
|
||||
assert isinstance(left, str)
|
||||
assert start - eat == int(left)
|
||||
assert start_fruits[fruits]['start'] == start
|
||||
assert start_fruits[fruits]['eat'] == eat
|
||||
|
||||
|
||||
@scenario(
|
||||
'outline_feature.feature',
|
||||
'Outlined given, when, thens',
|
||||
example_converters=dict(start=int, eat=float, left=str)
|
||||
)
|
||||
def test_outlined_feature():
|
||||
assert test_outlined.parametrize.args == (
|
||||
[u'start', u'eat', u'left'], [[12, 5.0, '7'], [5, 4.0, '1']])
|
||||
assert test_outlined_feature.parametrize.args == (
|
||||
['start', 'eat', 'left'],
|
||||
[[12, 5.0, '7'], [5, 4.0, '1']],
|
||||
['fruits'],
|
||||
[[u'oranges'], [u'apples']]
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue