def test_parse_feature_with_ignored_tag(self): """ Test parsing a feature which is not part of the feature tag expression """ feature = """ @some_feature Feature: some feature Scenario: foo When I have a normal scenario Then I expect nothing special """ with NamedTemporaryFile("w+") as featurefile: featurefile.write(feature) featurefile.flush() core = Mock() parser = FeatureParser( core, featurefile.name, 1, feature_tag_expr=tagexpressions.parse('not some_feature')) feature = parser.parse() feature.should.be.none
def _decorator(self, *args, **kwargs): """ Actual hook decorator """ if len(args) == 1 and len(kwargs) == 0 and callable(args[0]): func = args[0] # hook was called without argument -> legacy! HookRegistry().register( self._when, what, func ) # pylint: disable=protected-access else: # hook was called with argument on_tags = kwargs.get("on_tags") order = kwargs.get("order") if on_tags: expr = tagexpressions.parse(on_tags) on_tags = lambda tags: expr.evaluate(tags) def func(f): HookRegistry().register( self._when, what, f, order, on_tags) return f return func
def call(self, what, when, only_formatters, tagged_model, *args, **kwargs): """Calls a registered Hook""" hooks = self._hooks[when][what] for hook_impl in hooks: if not hook_impl.always: if only_formatters and not hook_impl.is_formatter: continue #: holds a flag whether or not the Hook actually has to be called # which is depenend on the `on_tags` setting of the HookImpl. call_hook = True if hook_impl.on_tags: tag_expression = tagexpressions.parse(" or ".join( hook_impl.on_tags)) # get the Tags for models which actually have Tags tags = (tagged_model.get_all_tags() if hasattr( tagged_model, "get_all_tags") else []) call_hook = tag_expression.evaluate([t.name for t in tags]) if not call_hook: continue try: hook_impl(tagged_model, *args, **kwargs) except Exception as exc: raise HookExecError(hook_impl, exc) from exc
def __init__(self, command_line_config): for opt_key, opt_value in command_line_config.items(): setattr(self, opt_key, opt_value) # make some configuration options easily accessible if hasattr(self, "tags") and self.tags: try: self.tag_expression = parse(self.tags) except Exception as exc: raise RadishError( "The given Tag Expression '{}' has Syntax Errors. " "Please consult https://github.com/timofurrer/tag-expressions " "for detailed information about the Tag Expression Syntax". format(self.tags)) from exc else: self.tag_expression = None
def test_parse_feature_with_ignored_scenario(self): """ Test parsing a feature which has an ignored scenario by a given tag expression """ feature = """ Feature: some feature @good_case Scenario: foo When I have a normal scenario Then I expect nothing special @bad_case Scenario: bad case Given I have the number 1 When I add 3 to my number Then I expect my number not to be 4 @good_case Scenario: foo second it When I have a normal scenario Then I expect nothing special """ with NamedTemporaryFile("w+") as featurefile: featurefile.write(feature) featurefile.flush() core = Mock() parser = FeatureParser( core, featurefile.name, 1, scenario_tag_expr=tagexpressions.parse('not bad_case')) feature = parser.parse() feature.scenarios.should.have.length_of(2)
Test parsing Feature and Scenario Tags """ # when feature = parser.parse() # then assert feature.tags == expected_feature_tags assert len(feature.scenarios) == len(expected_scenarios_tags) for scenario, expected_scenario_tags in zip(feature.scenarios, expected_scenarios_tags): assert scenario.tags == expected_scenario_tags @pytest.mark.parametrize('parser', [('tags-ignored-feature', [], { 'tag_expr': tagexpressions.parse('not foo') })], indirect=['parser']) def test_parse_ignored_feature_via_tag(parser): """ Test parsing a Feature which is ignored because of a Tag """ # when feature = parser.parse() # then assert feature is None @pytest.mark.parametrize('parser', [('tags-ignored-scenario', [], {
], 2, ) # then assert len(scenario.examples[0].steps) == 2 assert len(scenario.examples[1].steps) == 2 assert scenario.steps is not scenario.examples[0].steps assert scenario.steps is not scenario.examples[1].steps @pytest.mark.parametrize( "tagexpression, scenario_ids, expected_has_to_run", [ (None, [], True), (parse("tag-a"), [], True), (parse("tag-c"), [], True), (parse("tag-X"), [], False), (None, [1], True), (None, [3], True), (None, [-1], False), (parse("tag-a"), [-1], False), (parse("tag-X"), [1], False), (parse("tag-X"), [3], False), (parse("tag-a"), [3], True), ], ids=[ "no tagexpression, no scenario_ids => RUN", "tagexpression match in Scenario Tags, no scenario_ids => RUN", "tagexpression match in Feature Tags, no scenario_ids => RUN", "tagexpression no match, no scenario_ids => NO RUN",
def main(): """ Entrypont to radish. Setup up configuration, loads extensions, reads feature files and runs radish """ # note: using doc string for usage, messes up Sphinx documantation usage = """ Usage: radish show <features> [--expand] [--no-ansi] radish <features>... [-b=<basedir> | --basedir=<basedir>] [-e | --early-exit] [--debug-steps] [-t | --with-traceback] [-m=<marker> | --marker=<marker>] [-p=<profile> | --profile=<profile>] [-d | --dry-run] [-s=<scenarios> | --scenarios=<scenarios>] [--shuffle] [--feature-tags=<feature_tags>] [--scenario-tags=<scenario_tags>] {0} radish (-h | --help) radish (-v | --version) Arguments: features feature files to run Options: -h --help show this screen -v --version show version -e --early-exit stop the run after the first failed step --debug-steps debugs each step -t --with-traceback show the Exception traceback when a step fails -m=<marker> --marker=<marker> specify the marker for this run [default: time.time()] -p=<profile> --profile=<profile> specify the profile which can be used in the step/hook implementation -b=<basedir> --basedir=<basedir> set base dir from where the step.py and terrain.py will be loaded [default: $PWD/radish] -d --dry-run make dry run for the given feature files -s=<scenarios> --scenarios=<scenarios> only run the specified scenarios (comma separated list) --shuffle shuttle run order of features and scenarios --feature-tags=<feature_tags> only run features with the given tags --scenario-tags=<scenario_tags> only run scenarios with the given tags --expand expand the feature file (all preconditions) {1} (C) Copyright by Timo Furrer <*****@*****.**> """ # load extensions load_modules(os.path.join(os.path.dirname(__file__), "extensions")) extensions = ExtensionRegistry() # add arguments from extensions to the usage usage = usage.format(extensions.get_options(), extensions.get_option_description()) sys.excepthook = catch_unhandled_exception # add version to the usage arguments = docopt("radish {0}\n{1}".format(__VERSION__, usage), version=__VERSION__) # store all arguments to configuration dict in terrain.world setup_config(arguments) # load needed extensions extensions.load(world.config) core = Core() feature_files = [] for given_feature in world.config.features: if not os.path.exists(given_feature): raise FeatureFileNotFoundError(given_feature) if os.path.isdir(given_feature): feature_files.extend(utils.recursive_glob(given_feature, "*.feature")) continue feature_files.append(given_feature) # parse feature and scenario tag expressions feature_tag_expression = None if world.config.feature_tags: feature_tag_expression = tagexpressions.parse(world.config.feature_tags) scenario_tag_expression = None if world.config.scenario_tags: scenario_tag_expression = tagexpressions.parse(world.config.scenario_tags) core.parse_features(feature_files, feature_tag_expression, scenario_tag_expression) if not core.features or sum(len(f.scenarios) for f in core.features) == 0: print(colorful.bold_red('Error: ') + colorful.red('please specify at least one feature to run')) if feature_tag_expression or scenario_tag_expression: print(colorful.red('You have specified a feature or scenario expression. Make sure those are valid and actually yield some features to run.')) return 1 argument_dispatcher = [ ((lambda: world.config.show), show_features), ((lambda: True), run_features) ] # radish command dispatching for to_run, method in argument_dispatcher: if to_run(): return method(core)
def test_complex_evaluation(infix, values, expected): """Test complex tag expression evaluation""" assert parse(infix).evaluate(values) == expected
def test_basic_evaluation(infix, values, expected): """Test basic tag expression evaluation""" assert parse(infix).evaluate(values) == expected
def test_parser(infix, expected): """Test the tag expression parser""" assert str(parse(infix)) == expected
def main(args=None): """ Entrypont to radish. Setup up configuration, loads extensions, reads feature files and runs radish """ if args is None: args = sys.argv[1:] # note: using doc string for usage, messes up Sphinx documantation usage = """ Usage: radish show <features> [--expand] [--no-ansi] radish <features>... [-b=<basedir> | --basedir=<basedir>...] [-e | --early-exit] [--debug-steps] [-t | --with-traceback] [-m=<marker> | --marker=<marker>] [-p=<profile> | --profile=<profile>] [-d | --dry-run] [-s=<scenarios> | --scenarios=<scenarios>] [--shuffle] [--tags=<tags>] [--wip] [-f=<formatter> | --formatter=<formatter>] {0} radish (-h | --help) radish (-v | --version) Arguments: features feature files to run Options: -h --help show this screen -v --version show version -e --early-exit stop the run after the first failed step --debug-steps debugs each step -t --with-traceback show the Exception traceback when a step fails -m=<marker> --marker=<marker> specify the marker for this run [default: time.time()] -p=<profile> --profile=<profile> specify the profile which can be used in the step/hook implementation -b=<basedir> --basedir=<basedir>... set base dir from where the step.py and terrain.py will be loaded. [default: $PWD/radish] You can specify -b|--basedir multiple times or split multiple paths with a colon (:) similar to $PATH. All files will be imported. -d --dry-run make dry run for the given feature files -s=<scenarios> --scenarios=<scenarios> only run the specified scenarios (comma separated list) --shuffle shuttle run order of features and scenarios --tags=<feature_tags> only run Scenarios with the given tags --wip expects all tests to fail instead of succeeding -f=<formatter> --formatter=<formatter> the output formatter which should be used. [default: gherkin] --expand expand the feature file (all preconditions) {1} (C) Copyright by Timo Furrer <*****@*****.**> """ warnings.simplefilter("always", DeprecationWarning) # load extensions load_modules(os.path.join(os.path.dirname(__file__), "extensions")) extensions = ExtensionRegistry() # add arguments from extensions to the usage usage = usage.format(extensions.get_options(), extensions.get_option_description()) sys.excepthook = catch_unhandled_exception # add version to the usage arguments = docopt("radish {0}\n{1}".format(__VERSION__, usage), argv=args, version=__VERSION__) # store all arguments to configuration dict in terrain.world setup_config(arguments) # disable colors if necessary if world.config.no_ansi: colorful.disable() else: colorful.use_8_ansi_colors() # load needed extensions extensions.load(world.config) core = Core() if world.config.profile: msg = ( "Command line argument -p/--profile will be removed in a future version. Please " "use -u/--user-data instead.") warnings.warn(msg, DeprecationWarning, stacklevel=1) feature_files = [] for given_feature in world.config.features: if not os.path.exists(given_feature): raise FeatureFileNotFoundError(given_feature) if os.path.isdir(given_feature): feature_files.extend( utils.recursive_glob(given_feature, "*.feature")) continue feature_files.append(given_feature) # parse tag expressions tag_expression = None if world.config.tags: tag_expression = tagexpressions.parse(world.config.tags) core.parse_features(feature_files, tag_expression) if not core.features or sum(len(f.scenarios) for f in core.features) == 0: print( colorful.bold_red("Error: ") + colorful.red("please specify at least one feature to run")) if tag_expression: print( colorful.red( "You have specified a tag expression. Make sure those are valid and actually yield some Scenarios to run." )) return 1 argument_dispatcher = [ ((lambda: world.config.show), show_features), ((lambda: True), run_features), ] # radish command dispatching for to_run, method in argument_dispatcher: if to_run(): return method(core)
def main(args=None): """ Entrypont to radish. Setup up configuration, loads extensions, reads feature files and runs radish """ if args is None: args = sys.argv[1:] # note: using doc string for usage, messes up Sphinx documantation usage = """ Usage: radish show <features> [--expand] [--no-ansi] radish <features>... [-b=<basedir> | --basedir=<basedir>...] [-e | --early-exit] [--debug-steps] [-t | --with-traceback] [-m=<marker> | --marker=<marker>] [-p=<profile> | --profile=<profile>] [-d | --dry-run] [-s=<scenarios> | --scenarios=<scenarios>] [--shuffle] [--tags=<tags>] [--wip] [-f=<formatter> | --formatter=<formatter>] {0} radish (-h | --help) radish (-v | --version) Arguments: features feature files to run Options: -h --help show this screen -v --version show version -e --early-exit stop the run after the first failed step --debug-steps debugs each step -t --with-traceback show the Exception traceback when a step fails -m=<marker> --marker=<marker> specify the marker for this run [default: time.time()] -p=<profile> --profile=<profile> specify the profile which can be used in the step/hook implementation -b=<basedir> --basedir=<basedir>... set base dir from where the step.py and terrain.py will be loaded. [default: $PWD/radish] You can specify -b|--basedir multiple times or split multiple paths with a colon (:) similar to $PATH. All files will be imported. -d --dry-run make dry run for the given feature files -s=<scenarios> --scenarios=<scenarios> only run the specified scenarios (comma separated list) --shuffle shuttle run order of features and scenarios --tags=<feature_tags> only run Scenarios with the given tags --wip expects all tests to fail instead of succeeding -f=<formatter> --formatter=<formatter> the output formatter which should be used. [default: gherkin] --expand expand the feature file (all preconditions) {1} (C) Copyright by Timo Furrer <*****@*****.**> """ warnings.simplefilter("always", DeprecationWarning) # load extensions load_modules(os.path.join(os.path.dirname(__file__), "extensions")) extensions = ExtensionRegistry() # add arguments from extensions to the usage usage = usage.format(extensions.get_options(), extensions.get_option_description()) sys.excepthook = catch_unhandled_exception # add version to the usage arguments = docopt( "radish {0}\n{1}".format(__VERSION__, usage), argv=args, version=__VERSION__ ) # store all arguments to configuration dict in terrain.world setup_config(arguments) # disable colors if necessary if world.config.no_ansi: colorful.disable() else: colorful.use_8_ansi_colors() # load needed extensions extensions.load(world.config) core = Core() if world.config.profile: msg = ( "Command line argument -p/--profile will be removed in a future version. Please " "use -u/--user-data instead." ) warnings.warn(msg, DeprecationWarning, stacklevel=1) feature_files = [] for given_feature in world.config.features: if not os.path.exists(given_feature): raise FeatureFileNotFoundError(given_feature) if os.path.isdir(given_feature): feature_files.extend(utils.recursive_glob(given_feature, "*.feature")) continue feature_files.append(given_feature) # parse tag expressions tag_expression = None if world.config.tags: tag_expression = tagexpressions.parse(world.config.tags) core.parse_features(feature_files, tag_expression) if not core.features or sum(len(f.scenarios) for f in core.features) == 0: utils.console_write(colorful.bold_red("Error: ") + colorful.red("No feature or no scenario specified in at least one of the given feature files") ) if tag_expression: utils.console_write(colorful.red( "You have specified a tag expression. Make sure those are valid and actually yield some Scenarios to run." ) ) return 1 argument_dispatcher = [ ((lambda: world.config.show), show_features), ((lambda: True), run_features), ] # radish command dispatching for to_run, method in argument_dispatcher: if to_run(): return method(core)
""" # when feature = parser.parse() # then assert feature.tags == expected_feature_tags assert len(feature.scenarios) == len(expected_scenarios_tags) for scenario, expected_scenario_tags in zip( feature.scenarios, expected_scenarios_tags ): assert scenario.tags == expected_scenario_tags @pytest.mark.parametrize( "parser", [("tags-ignored-feature", [], {"tag_expr": tagexpressions.parse("not foo")})], indirect=["parser"], ) def test_parse_ignored_feature_via_tag(parser): """ Test parsing a Feature which is ignored because of a Tag """ # when feature = parser.parse() # then assert feature is None @pytest.mark.parametrize( "parser",