Skip to content

Commit d1eaf99

Browse files
pauk-slonolegpidsadnyi
authored andcommitted
Add --gherkin-terminal-reporter-expanded option (#222)
1 parent 7c6ba36 commit d1eaf99

File tree

5 files changed

+115
-5
lines changed

5 files changed

+115
-5
lines changed

pytest_bdd/gherkin_terminal_reporter.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
# -*- encoding: utf-8 -*-
22

3+
import re
4+
35
from _pytest.terminal import TerminalReporter
46

7+
from .feature import STEP_PARAM_RE
8+
59

610
def add_options(parser):
711
group = parser.getgroup("terminal reporting", "reporting", after="general")
@@ -14,6 +18,13 @@ def add_options(parser):
1418
"enable gherkin output"
1519
)
1620
)
21+
group._addoption(
22+
"--gherkin-terminal-reporter-expanded",
23+
action="store_true",
24+
dest="expand",
25+
default=False,
26+
help="expand scenario outlines into scenarios and fill in the step names",
27+
)
1728

1829

1930
def configure(config):
@@ -89,10 +100,25 @@ def pytest_runtest_logreport(self, report):
89100
self._tw.write(report.scenario['name'], **scenario_markup)
90101
self._tw.write('\n')
91102
for step in report.scenario['steps']:
103+
if self.config.option.expand:
104+
step_name = self._format_step_name(step['name'], **report.scenario['example_kwargs'])
105+
else:
106+
step_name = step['name']
92107
self._tw.write(' {} {}\n'.format(step['keyword'],
93-
step['name']), **scenario_markup)
108+
step_name), **scenario_markup)
94109
self._tw.write(' ' + word, **word_markup)
95110
self._tw.write('\n\n')
96111
else:
97112
return TerminalReporter.pytest_runtest_logreport(self, rep)
98113
self.stats.setdefault(cat, []).append(rep)
114+
115+
def _format_step_name(self, step_name, **example_kwargs):
116+
while True:
117+
param_match = re.search(STEP_PARAM_RE, step_name)
118+
if not param_match:
119+
break
120+
param_token = param_match.group(0)
121+
param_name = param_match.group(1)
122+
param_value = example_kwargs[param_name]
123+
step_name = step_name.replace(param_token, param_value)
124+
return step_name

pytest_bdd/reporting.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import time
88

9+
from .feature import force_unicode
10+
911

1012
class StepReport(object):
1113

@@ -60,7 +62,7 @@ def duration(self):
6062

6163
class ScenarioReport(object):
6264

63-
"""Scenario excecution report."""
65+
"""Scenario execution report."""
6466

6567
def __init__(self, scenario, node):
6668
"""Scenario report constructor.
@@ -81,6 +83,10 @@ def __init__(self, scenario, node):
8183
self.param_index = param_values.index(node_param_values)
8284
elif tuple(node_param_values) in param_values:
8385
self.param_index = param_values.index(tuple(node_param_values))
86+
self.example_kwargs = {
87+
example_param: force_unicode(node.funcargs[example_param])
88+
for example_param in scenario.get_example_params()
89+
}
8490

8591
@property
8692
def current_step_report(self):
@@ -129,7 +135,8 @@ def serialize(self):
129135
"rows": params,
130136
"row_index": self.param_index,
131137
}
132-
] if scenario.examples else []
138+
] if scenario.examples else [],
139+
"example_kwargs": self.example_kwargs,
133140
}
134141

135142
def fail(self):

tests/feature/gherkin_terminal_reporter.feature

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,8 @@ Feature: Gherkin terminal reporter
4040
Given there is gherkin scenario with broken implementation
4141
When tests are run with --showlocals
4242
Then error traceback contains local variable descriptions
43+
44+
Scenario: Should step parameters be replaced by their values
45+
Given there is gherkin scenario outline implemented
46+
When tests are run with step expanded mode
47+
Then output must contain parameters values

tests/feature/test_gherkin_terminal_reporter.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ def test_Should_local_variables_be_displayed_when___showlocals_option_is_used():
5454
pass
5555

5656

57+
@scenario('gherkin_terminal_reporter.feature',
58+
'Should step parameters be replaced by their values')
59+
def test_Should_step_parameters_be_replaced_by_their_values():
60+
pass
61+
62+
5763
@pytest.fixture(params=[0, 1, 2],
5864
ids=['compact mode', 'line per test', 'verbose'])
5965
def verbosity_mode(request):
@@ -104,6 +110,47 @@ def test_scenario_1():
104110
""")
105111

106112

113+
@given("there is gherkin scenario outline implemented")
114+
def gherkin_scenario_outline(testdir):
115+
example = {
116+
'start': 12,
117+
'eat': 5,
118+
'left': 7,
119+
}
120+
testdir.makefile('.feature', test="""
121+
Feature: Gherkin terminal output feature
122+
Scenario Outline: Scenario example 2
123+
Given there are <start> cucumbers
124+
When I eat <eat> cucumbers
125+
Then I should have <left> cucumbers
126+
127+
Examples:
128+
| start | eat | left |
129+
|{start}|{eat}|{left}|
130+
""".format(**example))
131+
testdir.makepyfile(test_gherkin="""
132+
import pytest
133+
from pytest_bdd import given, when, scenario, then
134+
135+
@given('there are <start> cucumbers')
136+
def start_cucumbers(start):
137+
return start
138+
139+
@when('I eat <eat> cucumbers')
140+
def eat_cucumbers(start_cucumbers, eat):
141+
pass
142+
143+
@then('I should have <left> cucumbers')
144+
def should_have_left_cucumbers(start_cucumbers, start, eat, left):
145+
pass
146+
147+
@scenario('test.feature', 'Scenario example 2')
148+
def test_scenario_2():
149+
pass
150+
""")
151+
return example
152+
153+
107154
@when("tests are run")
108155
def tests_are_run(testdir, test_execution):
109156
test_execution['regular'] = testdir.runpytest()
@@ -137,6 +184,16 @@ def tests_are_run_with_very_verbose_mode(testdir, test_execution):
137184
test_execution['gherkin'] = testdir.runpytest('--gherkin-terminal-reporter', '-vv')
138185

139186

187+
@when("tests are run with step expanded mode")
188+
def tests_are_run_with_step_expanded_mode(testdir, test_execution):
189+
test_execution['regular'] = testdir.runpytest('-vv')
190+
test_execution['gherkin'] = testdir.runpytest(
191+
'--gherkin-terminal-reporter',
192+
'--gherkin-terminal-reporter-expanded',
193+
'-vv',
194+
)
195+
196+
140197
@then("output should contain single line feature description")
141198
def output_should_contain_single_line_feature_description(test_execution):
142199
ghe = test_execution['gherkin']
@@ -276,3 +333,14 @@ def error_traceback_contains_local_variable_descriptions(test_execution):
276333
assert ghe.ret
277334
ghe.stdout.fnmatch_lines('''request*=*<FixtureRequest for *''')
278335
ghe.stdout.fnmatch_lines('''local_var*=*''')
336+
337+
338+
@then("output must contain parameters values")
339+
def output_output_must_contain_parameters_values(test_execution, gherkin_scenario_outline):
340+
ghe = test_execution['gherkin']
341+
assert ghe.ret == 0
342+
ghe.stdout.fnmatch_lines('*Scenario: Scenario example 2')
343+
ghe.stdout.fnmatch_lines('*Given there are {start} cucumbers'.format(**gherkin_scenario_outline))
344+
ghe.stdout.fnmatch_lines('*When I eat {eat} cucumbers'.format(**gherkin_scenario_outline))
345+
ghe.stdout.fnmatch_lines('*Then I should have {left} cucumbers'.format(**gherkin_scenario_outline))
346+
ghe.stdout.fnmatch_lines('*PASSED')

tests/feature/test_report.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ def should_have_left_cucumbers(start_cucumbers, start, eat, left):
109109
'name': u'some other passing step',
110110
'type': 'given'}],
111111
'tags': [u'scenario-passing-tag'],
112-
'examples': []}
112+
'examples': [],
113+
'example_kwargs': {}}
113114

114115
assert report == expected
115116

@@ -135,7 +136,8 @@ def should_have_left_cucumbers(start_cucumbers, start, eat, left):
135136
'name': u'a failing step',
136137
'type': 'given'}],
137138
'tags': [u'scenario-failing-tag'],
138-
'examples': []}
139+
'examples': [],
140+
'example_kwargs': {}}
139141
assert report == expected
140142

141143
report = result.matchreport('test_outlined[12-5.0-7]', when='call').scenario
@@ -171,6 +173,7 @@ def should_have_left_cucumbers(start_cucumbers, start, eat, left):
171173
'row_index': 0,
172174
'rows': [['start', 'eat', 'left'],
173175
[[12, 5.0, '7'], [5, 4.0, '1']]]}],
176+
'example_kwargs': {'eat': '5.0', 'left': '7', 'start': '12'},
174177
}
175178
assert report == expected
176179

@@ -207,6 +210,7 @@ def should_have_left_cucumbers(start_cucumbers, start, eat, left):
207210
'row_index': 1,
208211
'rows': [['start', 'eat', 'left'],
209212
[[12, 5.0, '7'], [5, 4.0, '1']]]}],
213+
'example_kwargs': {'eat': '4.0', 'left': '1', 'start': '5'},
210214
}
211215
assert report == expected
212216

0 commit comments

Comments
 (0)