def assert_step_not_match( step: Step, expected_step_func: str, step_registry: StepRegistry ): """Assert that the Step doesn't match a Step Implementation from the Registry""" print( "{} STEP '{}' SHOULD NOT MATCH {}".format( cf.orange(">>"), cf.deepSkyBlue3("{} {}".format(step.keyword, step.text)), cf.deepSkyBlue3(expected_step_func if expected_step_func else "ANY"), ), end=" ", flush=True, ) # match the step text from the config with one from the registry try: matcher.match_step(step, step_registry) except StepImplementationNotFoundError: print(cf.bold_forestGreen("✔")) return True matched_step_func = step.step_impl.func if matched_step_func.__name__ == expected_step_func: print_failure( matched_step_func, [ "Expected Step Text matched {} but it shouldn't".format( expected_step_func ) ], ) return False print(cf.bold_forestGreen("✔")) return True
def test_invalid_parse_pattern(): """ Test failure for invalid Parse pattern """ # given invalid_pattern = 'Given I have the number {:d {}' # when with pytest.raises(errors.StepPatternError) as exc: matcher.match_step('Given I have the number 5', {invalid_pattern: int}) assert str(exc.value).startswith( "Cannot compile pattern 'Given I have the number {:d {}' of step 'int': " )
def test_matcher_should_raise_error_when_no_step_impl_found(mocker): """The matcher should raise an error when no Step Implementation is found""" # given registry_mock = mocker.MagicMock() registry_mock.step_implementations.return_value = [] step = Step(1, "Given", "Given", "pattern", None, None, None, None) step.set_scenario(mocker.MagicMock(name="Scenario")) # then with pytest.raises(StepImplementationNotFoundError) as excinfo: # when match_step(step, registry_mock) # then assert excinfo.value.step == step
def test_matcher_should_match_step_impl_with_regex_pattern(mocker): """The matcher should match a Step with a parse-type pattern""" # given step_impl = StepImpl("Given", re.compile(r"pattern"), None) registry_mock = mocker.MagicMock() registry_mock.step_implementations.return_value = [step_impl] step = Step(1, "Given", "Given", "pattern", None, None, None, None) step.set_scenario(mocker.MagicMock(name="Scenario")) # when match_step(step, registry_mock) # then assert step.step_impl == step_impl assert isinstance(step.step_impl_match, RegexStepImplMatcher.Match)
def test_step_match(sentence, expected_step, expected_arguments, steps): sys.stdout.write('{0} STEP "{1}" SHOULD MATCH {2} '.format( colorful.yellow('>>'), colorful.cyan(sentence), colorful.cyan(expected_step))) result = match_step(sentence, steps) if not result: output_failure( None, ['Expected sentence didn\'t match any step implementation']) return False if expected_step != result.func.__name__: output_failure(result.func, [ 'Expected sentence matched {0} instead of {1}'.format( result.func.__name__, expected_step) ]) return False if expected_arguments: arguments = merge_step_args(result) expected_arguments = { k: v for expected_arguments in expected_arguments for k, v in expected_arguments.items() } argument_errors = check_step_arguments(expected_arguments, arguments) if argument_errors: output_failure(result.func, argument_errors) return False print(u(colorful.bold_green(u'✔'))) return True
def test_step_not_match(sentence, expected_not_matching_step, steps): step_to_print = ( colorful.cyan(expected_not_matching_step) if expected_not_matching_step else "ANY" ) sys.stdout.write( '{0} STEP "{1}" SHOULD NOT MATCH {2} '.format( colorful.yellow(">>"), colorful.cyan(sentence), step_to_print ) ) result = match_step(sentence, steps) if result: if ( not expected_not_matching_step or result.func.__name__ == expected_not_matching_step ): output_failure( None, [ "Expected sentence did match {0} but it shouldn't".format( expected_not_matching_step ) ], ) return False print(u(colorful.bold_green("✔"))) return True
def test_step_matches(match_config, steps): """ Test if the given match config matches the actual matched step implementations. """ failed = 0 passed = 0 for item in match_config: if 'sentence' not in item or 'should_match' not in item: raise ValueError( 'You have to provide a sentence and the function name which should be matched (should_match)' ) sentence = item['sentence'] expected_step = item['should_match'] sys.stdout.write('{0} STEP "{1}" SHOULD MATCH {2} '.format( colorful.brown('>>'), colorful.cyan(sentence), colorful.cyan(expected_step))) result = match_step(item['sentence'], steps) if not result: output_failure( None, ['Expected sentence didn\'t match any step implemention']) failed += 1 continue if expected_step != result.func.__name__: output_failure(result.func, [ 'Expected sentence matched {0} instead of {1}'.format( result.func.__name__, expected_step) ]) failed += 1 continue expected_arguments = item.get('with-arguments') if expected_arguments: arguments = merge_step_args(result) expected_arguments = { k: v for expected_arguments in expected_arguments for k, v in expected_arguments.items() } argument_errors = check_step_arguments(expected_arguments, arguments) if argument_errors: output_failure(result.func, argument_errors) failed += 1 continue # check if arguments match print(colorful.bold_green('✔')) passed += 1 return failed, passed
def test_no_step_match(given_sentence, given_steps): """ Test failing to match a sentence with given Steps """ # given & when match = matcher.match_step(given_sentence, given_steps) # then assert match is None
def test_matcher_should_match_step_impl_with_step_with_constants(mocker): """The matcher should match a Step with Constants""" # given step_impl = StepImpl("Given", "pattern with A and B", None) registry_mock = mocker.MagicMock() registry_mock.step_implementations.return_value = [step_impl] step = Step(1, "Given", "Given", "pattern with ${x} and ${y}", None, None, None, None) scenario_mock = mocker.MagicMock(name="Scenario") scenario_mock.constants = {"x": "A", "y": "B"} step.set_scenario(scenario_mock) # when match_step(step, registry_mock) # then assert step.step_impl == step_impl assert isinstance(step.step_impl_match, ParseTypeStepImplMatcher.Match)
def test_match_steps(self): """ Test matching steps from feature files with registered steps """ steps = {re.compile(r"Given I have the number (\d+)"): "some_func", re.compile(r"I add (\d+) to my number"): "some_other_func"} match, func = match_step("Given I have the number 5", steps) arguments, keyword_arguments = match.evaluate() arguments.should.be.equal(("5",)) keyword_arguments.should.be.equal({}) func.should.be.equal("some_func") match, func = match_step("When I add 2 to my number", steps) arguments, keyword_arguments = match.evaluate() arguments.should.be.equal(("2",)) keyword_arguments.should.be.equal({}) func.should.be.equal("some_other_func") match = match_step("when I call a non-existing step", steps) match.should.be.none # pylint: disable=pointless-statement
def test_match_sentence_with_steps(given_sentence, given_steps, expected_argument_match_type, expected_func_match): """ Test matching a sentence with given Steps """ # given & when match = matcher.match_step(given_sentence, given_steps) # then assert isinstance(match.argument_match, expected_argument_match_type) assert match.func == expected_func_match
def test_matcher_should_raise_error_when_no_matcher_for_pattern_type(mocker): """ The matcher should raise an error when no Matcher supports a Step Implementation Pattern Type """ # given class NotSupportedPatternType: pass step_impl = StepImpl("Given", NotSupportedPatternType(), None) registry_mock = mocker.MagicMock() registry_mock.step_implementations.return_value = [step_impl] step = Step(1, "Given", "Given", "pattern", None, None, None, None) step.set_scenario(mocker.MagicMock(name="Scenario")) # then with pytest.raises(StepImplementationPatternNotSupported) as excinfo: # when match_step(step, registry_mock) # then assert excinfo.value.step_impl == step_impl
def test_matcher_should_match_best_step_impl_candidate(mocker): """The matcher should match the best matching Step Implementation Candidate""" # given step_impl_candidate_1 = StepImpl("Given", re.compile(r"fooo"), None) step_impl_candidate_2 = StepImpl("Given", re.compile(r"foo"), None) step_impl_candidate_3 = StepImpl("Given", re.compile(r"foooo"), None) step_impl_no_candidate = StepImpl("Given", re.compile(r"meh"), None) registry_mock = mocker.MagicMock() registry_mock.step_implementations.return_value = [ step_impl_candidate_1, step_impl_candidate_2, step_impl_candidate_3, step_impl_no_candidate, ] step = Step(1, "Given", "Given", "foo", None, None, None, None) step.set_scenario(mocker.MagicMock(name="Scenario")) # when match_step(step, registry_mock) # then assert step.step_impl == step_impl_candidate_2
def test_step_not_match(sentence, expected_not_matching_step, steps): step_to_print = colorful.cyan( expected_not_matching_step) if expected_not_matching_step else 'ANY' sys.stdout.write('{0} STEP "{1}" SHOULD NOT MATCH {2} '.format( colorful.yellow('>>'), colorful.cyan(sentence), step_to_print)) result = match_step(sentence, steps) if result: if not expected_not_matching_step or result.func.__name__ == expected_not_matching_step: output_failure(None, [ 'Expected sentence did match {0} but it shouldn\'t'.format( expected_not_matching_step) ]) return False print(u(colorful.bold_green(u'✔'))) return True
def test_step_not_match(sentence, expected_not_matching_step, steps): step_to_print = (colorful.cyan(expected_not_matching_step) if expected_not_matching_step else "ANY") sys.stdout.write('{0} STEP "{1}" SHOULD NOT MATCH {2} '.format( colorful.yellow(">>"), colorful.cyan(sentence), step_to_print)) result = match_step(sentence, steps) if result: if (not expected_not_matching_step or result.func.__name__ == expected_not_matching_step): output_failure( None, [ "Expected sentence did match {0} but it shouldn't".format( expected_not_matching_step) ], ) return False print(u(colorful.bold_green("✔"))) return True
def merge_step(step, steps): """ Merges a single step with the registered steps :param Step step: the step from a feature file to merge :param list steps: the registered steps """ match = match_step(step.context_sensitive_sentence, steps) if not match or not match.func: # repalced block of original method # instead of rising StepDefinitionNotFoundError adding no_implemented_step_stub_method # remove Gherkin step base words sentence = re.sub(r'^(And|Given|When|Then|But)\s*', '', step.sentence) # replace "quotedStrings" sentence = re.sub('([^"]|^)"([^"]+)"([^"]|$)', r'\1{0}\3'.format(quoted_string), sentence) if sentence not in steps: sentence = add_sentence(sentence) steps[sentence] = not_implemented_step_stub_method match = StepMatch(not_implemented_step_stub_method, ParseStepArguments(match)) step.definition_func = match.func step.argument_match = match.argument_match
def test_step_match(sentence, expected_step, expected_arguments, steps): sys.stdout.write( '{0} STEP "{1}" SHOULD MATCH {2} '.format( colorful.yellow(">>"), colorful.cyan(sentence), colorful.cyan(expected_step) ) ) result = match_step(sentence, steps) if not result: output_failure(None, ["Expected sentence didn't match any step implementation"]) return False if expected_step != result.func.__name__: output_failure( result.func, [ "Expected sentence matched {0} instead of {1}".format( result.func.__name__, expected_step ) ], ) return False if expected_arguments: arguments = merge_step_args(result) expected_arguments = { k: v for expected_arguments in expected_arguments for k, v in expected_arguments.items() } argument_errors = check_step_arguments(expected_arguments, arguments) if argument_errors: output_failure(result.func, argument_errors) return False print(u(colorful.bold_green("✔"))) return True
def assert_step_match( step: Step, expected_step_func: str, expected_step_arguments: List[Dict[str, Any]], step_registry: StepRegistry, ): """Assert that the Step correctly matches in the Registry""" print( "{} STEP '{}' SHOULD MATCH {}".format( cf.orange(">>"), cf.deepSkyBlue3("{} {}".format(step.keyword, step.text)), cf.deepSkyBlue3(expected_step_func), ), end=" ", flush=True, ) # match the step text from the config with one from the registry try: matcher.match_step(step, step_registry) except StepImplementationNotFoundError: print_failure(None, ["Expected Step Text didn't match any Step Implementation"]) return False # check if Step matches the correct Step Implementation Function matched_step_func = step.step_impl.func if matched_step_func.__name__ != expected_step_func: print_failure( matched_step_func, [ "Expected Step Text matched {} instead of {}".format( matched_step_func.__name__, expected_step_func ) ], ) return False # check if the Step has a match with the correct arguments if expected_step_arguments: # merge the Step's keyword and positional arguments into one dict args, kwargs = step.step_impl_match.evaluate() actual_step_arguments = utils.get_func_pos_args_as_kwargs( matched_step_func, args ) actual_step_arguments.update(kwargs) # turn the list of single-item-dicts to a multi-item dict # -> [{1: 2}, {3: 4}] --> {1: 2, 3: 4} # NOTE(TF) for Python 3.5 test reproducibility we need an OrderedDict -.^ expected_step_arguments = OrderedDict( ( argpair for argpairs in expected_step_arguments for argpair in argpairs.items() ) ) errors = assert_step_arguments(actual_step_arguments, expected_step_arguments) if errors: print_failure(matched_step_func, errors) return False print(cf.bold_forestGreen("✔")) return True