From d2ae7894daf6863b4b124943356ba89993dcac6f Mon Sep 17 00:00:00 2001 From: Milosz Sliwinski Date: Mon, 29 Oct 2018 09:18:03 +0100 Subject: [PATCH 1/4] Let gherkin-terminal-reporter-expanded enable gherkin output --- pytest_bdd/cucumber_json.py | 4 ++-- pytest_bdd/gherkin_terminal_reporter.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pytest_bdd/cucumber_json.py b/pytest_bdd/cucumber_json.py index 71b9feab0..41b8dc4c0 100644 --- a/pytest_bdd/cucumber_json.py +++ b/pytest_bdd/cucumber_json.py @@ -32,7 +32,7 @@ def add_options(parser): "--cucumberjson-expanded", "--cucumber-json-expanded", action="store_true", - dest="expand", + dest="cucumber_json_expanded", default=False, help="expand scenario outlines into scenarios and fill in the step names", ) @@ -42,7 +42,7 @@ def configure(config): cucumber_json_path = config.option.cucumber_json_path # prevent opening json log on slave nodes (xdist) if cucumber_json_path and not hasattr(config, "slaveinput"): - config._bddcucumberjson = LogBDDCucumberJSON(cucumber_json_path, expand=config.option.expand) + config._bddcucumberjson = LogBDDCucumberJSON(cucumber_json_path, expand=config.option.cucumber_json_expanded) config.pluginmanager.register(config._bddcucumberjson) diff --git a/pytest_bdd/gherkin_terminal_reporter.py b/pytest_bdd/gherkin_terminal_reporter.py index f846084a9..e3378767f 100644 --- a/pytest_bdd/gherkin_terminal_reporter.py +++ b/pytest_bdd/gherkin_terminal_reporter.py @@ -21,14 +21,14 @@ def add_options(parser): group._addoption( "--gherkin-terminal-reporter-expanded", action="store_true", - dest="expand", + dest="gherkin_expanded", default=False, - help="expand scenario outlines into scenarios and fill in the step names", + help="enable gherkin output, expand scenario outlines into scenarios and fill in the step names", ) def configure(config): - if config.option.gherkin_terminal_reporter: + if config.option.gherkin_terminal_reporter or config.option.gherkin_expanded: # Get the standard terminal reporter plugin and replace it with our current_reporter = config.pluginmanager.getplugin('terminalreporter') if current_reporter.__class__ != TerminalReporter: @@ -100,7 +100,7 @@ def pytest_runtest_logreport(self, report): self._tw.write(report.scenario['name'], **scenario_markup) self._tw.write('\n') for step in report.scenario['steps']: - if self.config.option.expand: + if self.config.option.gherkin_expanded: step_name = self._format_step_name(step['name'], **report.scenario['example_kwargs']) else: step_name = step['name'] From a26f4538735632450cdd1059afe705223e6fa91e Mon Sep 17 00:00:00 2001 From: Milosz Sliwinski Date: Wed, 14 Nov 2018 15:37:52 +0100 Subject: [PATCH 2/4] Use parametrize markers params for getting example_kwargs --- pytest_bdd/reporting.py | 32 ++++++++++++------- pytest_bdd/utils.py | 30 +++++++++++++++++ .../feature/gherkin_terminal_reporter.feature | 7 +++- tests/feature/outline_feature.feature | 1 + tests/feature/parametrized.feature | 4 +++ .../feature/test_gherkin_terminal_reporter.py | 19 +++++++++-- tests/feature/test_outline.py | 2 +- tests/feature/test_parametrized.py | 11 +++++++ 8 files changed, 91 insertions(+), 15 deletions(-) diff --git a/pytest_bdd/reporting.py b/pytest_bdd/reporting.py index f99d54c79..723105562 100644 --- a/pytest_bdd/reporting.py +++ b/pytest_bdd/reporting.py @@ -7,7 +7,7 @@ import time from .feature import force_unicode -from .utils import get_parametrize_markers_args +from .utils import get_parametrize_markers_args, get_parametrize_params class StepReport(object): @@ -73,20 +73,30 @@ def __init__(self, scenario, node): """ self.scenario = scenario self.step_reports = [] - self.param_index = None + parametrize_args = get_parametrize_markers_args(node) - if parametrize_args and scenario.examples: - param_names = parametrize_args[0] if isinstance(parametrize_args[0], (tuple, list)) else [ - parametrize_args[0]] - param_values = parametrize_args[1] + params = get_parametrize_params(parametrize_args) + + self.param_index = self.get_param_index(node, params) + self.example_kwargs = self.get_example_kwargs(node, params) + + def get_param_index(self, node, params): + if params: + param_names = params[0]['names'] + param_values = params[0]['values'] node_param_values = [node.funcargs[param_name] for param_name in param_names] if node_param_values in param_values: - self.param_index = param_values.index(node_param_values) + return param_values.index(node_param_values) elif tuple(node_param_values) in param_values: - self.param_index = param_values.index(tuple(node_param_values)) - self.example_kwargs = { - example_param: force_unicode(node.funcargs[example_param]) - for example_param in scenario.get_example_params() + return param_values.index(tuple(node_param_values)) + return None + + def get_example_kwargs(self, node, params): + params_names = (param['names'] for param in params) + all_names = sum(params_names, []) + return { + example_param_name: force_unicode(node.funcargs[example_param_name]) + for example_param_name in all_names } @property diff --git a/pytest_bdd/utils.py b/pytest_bdd/utils.py index 7fdfa7f23..a773eb097 100644 --- a/pytest_bdd/utils.py +++ b/pytest_bdd/utils.py @@ -110,3 +110,33 @@ def get_markers_args_using_iter_markers(node, mark_name): def get_markers_args_using_get_marker(node, mark_name): """Deprecated on pytest>=3.6""" return getattr(node.get_marker(mark_name), 'args', ()) + + +def get_parametrize_params(parametrize_args): + """Group parametrize markers arugments names and values. + + :param marker_args: json-serialized `Scenario` or `Feature`. + :return: `list` of `dict` in the form of: + [ + { + "names": ["name1", "name2", ...], + "values": [value1, value2, ...], + }, + ... + ] + """ + params = [] + for i in range(0, len(parametrize_args), 2): + params.append({ + 'names': _get_param_names(parametrize_args[i]), + 'values': parametrize_args[i+1] + }) + return params + + +def _get_param_names(names): + if not isinstance(names, (tuple, list)): + # As pytest.mark.parametrize has only one param name, + # it is not returned as a list. Convert it to list: + names = [names] + return names diff --git a/tests/feature/gherkin_terminal_reporter.feature b/tests/feature/gherkin_terminal_reporter.feature index 4f8d09396..95f2ceb7f 100644 --- a/tests/feature/gherkin_terminal_reporter.feature +++ b/tests/feature/gherkin_terminal_reporter.feature @@ -43,5 +43,10 @@ Feature: Gherkin terminal reporter Scenario: Should step parameters be replaced by their values Given there is gherkin scenario outline implemented - When tests are run with step expanded mode + When tests are run with step expanded option + Then output must contain parameters values + + Scenario: Should step parameters be replaced by their values also when used together with gherkin reporter option + Given there is gherkin scenario outline implemented + When tests are run with step expanded and gherkin reporter options Then output must contain parameters values diff --git a/tests/feature/outline_feature.feature b/tests/feature/outline_feature.feature index 98280b1d5..992fc81fa 100644 --- a/tests/feature/outline_feature.feature +++ b/tests/feature/outline_feature.feature @@ -4,6 +4,7 @@ Feature: Outline | start | eat | left | | 12 | 5 | 7 | | 5 | 4 | 1 | + | 4 | 2 | 2 | Scenario Outline: Outlined given, when, thens Given there are diff --git a/tests/feature/parametrized.feature b/tests/feature/parametrized.feature index 70953cc89..7febc15b9 100644 --- a/tests/feature/parametrized.feature +++ b/tests/feature/parametrized.feature @@ -2,3 +2,7 @@ Scenario: Parametrized given, when, thens Given there are cucumbers When I eat cucumbers Then I should have cucumbers + + +Scenario: Parametrized given - single param + Given there are cucumbers diff --git a/tests/feature/test_gherkin_terminal_reporter.py b/tests/feature/test_gherkin_terminal_reporter.py index 1fab65982..f2d989ce6 100644 --- a/tests/feature/test_gherkin_terminal_reporter.py +++ b/tests/feature/test_gherkin_terminal_reporter.py @@ -60,6 +60,12 @@ def test_Should_step_parameters_be_replaced_by_their_values(): pass +@scenario('gherkin_terminal_reporter.feature', + 'Should step parameters be replaced by their values also when used together with gherkin reporter option') +def test_Should_step_parameters_be_replaced_by_their_values_also_when_used_together_with_gherkin_reporter_option(): + pass + + @pytest.fixture(params=[0, 1, 2], ids=['compact mode', 'line per test', 'verbose']) def verbosity_mode(request): @@ -184,8 +190,17 @@ def tests_are_run_with_very_verbose_mode(testdir, test_execution): test_execution['gherkin'] = testdir.runpytest('--gherkin-terminal-reporter', '-vv') -@when("tests are run with step expanded mode") -def tests_are_run_with_step_expanded_mode(testdir, test_execution): +@when("tests are run with step expanded option") +def tests_are_run_with_step_expanded_option(testdir, test_execution): + test_execution['regular'] = testdir.runpytest('-vv') + test_execution['gherkin'] = testdir.runpytest( + '--gherkin-terminal-reporter-expanded', + '-vv', + ) + + +@when("tests are run with step expanded and gherkin reporter options") +def tests_are_run_with_step_expanded_and_gherkin_reporter_options(testdir, test_execution): test_execution['regular'] = testdir.runpytest('-vv') test_execution['gherkin'] = testdir.runpytest( '--gherkin-terminal-reporter', diff --git a/tests/feature/test_outline.py b/tests/feature/test_outline.py index afddaa815..ca6bcb155 100644 --- a/tests/feature/test_outline.py +++ b/tests/feature/test_outline.py @@ -168,7 +168,7 @@ def should_have_left_fruits(start_fruits, start, eat, left, fruits): def test_outlined_feature(request): assert get_parametrize_markers_args(request.node) == ( ['start', 'eat', 'left'], - [[12, 5.0, '7'], [5, 4.0, '1']], + [[12, 5.0, '7'], [5, 4.0, '1'], [4, 2.0, '2']], ['fruits'], [[u'oranges'], [u'apples']] ) diff --git a/tests/feature/test_parametrized.py b/tests/feature/test_parametrized.py index 7dfd76da9..bb8396b48 100644 --- a/tests/feature/test_parametrized.py +++ b/tests/feature/test_parametrized.py @@ -14,6 +14,17 @@ def test_parametrized(request, start, eat, left): """Test parametrized scenario.""" +@pytest.mark.parametrize( + 'start', [12] +) +@scenario( + 'parametrized.feature', + 'Parametrized given - single param', +) +def test_parametrized_single_param(request, start): + """Test parametrized scenario.""" + + @pytest.fixture(params=[1, 2]) def foo_bar(request): return 'bar' * request.param From f06f23c6ed32671056f1b9b5072d7955158ff845 Mon Sep 17 00:00:00 2001 From: Milosz Sliwinski Date: Thu, 15 Nov 2018 12:16:22 +0100 Subject: [PATCH 3/4] Fix for unicode steps in gherkin reporter --- pytest_bdd/gherkin_terminal_reporter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytest_bdd/gherkin_terminal_reporter.py b/pytest_bdd/gherkin_terminal_reporter.py index e3378767f..0d727895c 100644 --- a/pytest_bdd/gherkin_terminal_reporter.py +++ b/pytest_bdd/gherkin_terminal_reporter.py @@ -104,8 +104,8 @@ def pytest_runtest_logreport(self, report): step_name = self._format_step_name(step['name'], **report.scenario['example_kwargs']) else: step_name = step['name'] - self._tw.write(' {} {}\n'.format(step['keyword'], - step_name), **scenario_markup) + self._tw.write(u' {} {}\n'.format(step['keyword'], + step_name), **scenario_markup) self._tw.write(' ' + word, **word_markup) self._tw.write('\n\n') else: From d6fea087ab4c4b768cfc1e02fa44c14a0496bcb0 Mon Sep 17 00:00:00 2001 From: Milosz Sliwinski Date: Sun, 18 Nov 2018 15:24:59 +0100 Subject: [PATCH 4/4] get_parametrize_params docstring updated --- pytest_bdd/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytest_bdd/utils.py b/pytest_bdd/utils.py index a773eb097..c2121cc4d 100644 --- a/pytest_bdd/utils.py +++ b/pytest_bdd/utils.py @@ -113,9 +113,9 @@ def get_markers_args_using_get_marker(node, mark_name): def get_parametrize_params(parametrize_args): - """Group parametrize markers arugments names and values. + """Group parametrize markers arguments names and values. - :param marker_args: json-serialized `Scenario` or `Feature`. + :param parametrize_args: parametrize markers arguments. :return: `list` of `dict` in the form of: [ {