def run(filename, suite, as_str=None, scenario=r'.*', verbose=False, show_all_missing=True, **kwargs): # NOQA """Parse file and run tests on given suite. :param str filename: file name :param unittest.TestCase suite: TestCase instance :param string as_str: None to use file or a string containing the feature to parse :param string scenario: a regex pattern to match the scenario to run :param boolean verbose: be verbose :param boolean show_all_missing: show all missing steps """ formatter = kwargs.get('formatter', None) if verbose and not formatter: if has_color_support(): formatter = ColorTextFormatter() else: formatter = PlainTextFormatter() kwargs['formatter'] = formatter kwargs['show_all_missing'] = show_all_missing parser = Parser() ast = parser.parse_file(filename, scenario=scenario) if as_str is None \ else parser.parse_as_str(filename, as_str, scenario=scenario) return ast.evaluate(suite, **kwargs)
def test_should_report_on_all_failing_scenarios(self): self._add_failure_pattern = re.compile('Scenario: Add two numbers\n\s*Then the result should be "120" on the screen\n\s*.*AssertionError:\s*70 != 120', re.DOTALL) self._substract_failure_pattern = re.compile('Scenario: Subtract two numbers\n\s*Then the result should be "80" on the screen\n\s*.*AssertionError:\s*70 != 80', re.DOTALL) self._multiply_failure_pattern = re.compile('Scenario: Multiply two numbers\n\s*Then the result should be "12" on the screen\n\s*.*AssertionError:\s*3 != 12', re.DOTALL) self._division_failure_pattern = re.compile('Scenario: Divide two numbers\n\s*Then the result should be "4" on the screen\n\s*.*AssertionError:\s*2 != 4', re.DOTALL) filename = os.path.join(pwd, 'features/info_on_all_failing_scenarios.feature') ast = Parser().parse_file(filename) ast.evaluate(self)
def step_Morelia_evaluates_the_file(self): self.diagnostic = None try: language = self._get_language() p = Parser(language=language) self.file_contents.replace('\\#', '#') # note - this is how to unescape characters - DIY prefix = u'{}: Sample\n{}: Sample\n'.format(self.feature_keyword, self.scenario_keyword) p.parse_features(prefix + self.file_contents).evaluate(self) except (MissingStepError, AssertionError) as e: self.diagnostic = str(e)
def step_Morelia_evaluates_the_file(self): self.diagnostic = None try: p = Parser() self.file_contents.replace( "\\#", "#") # note - this is how to unescape characters - DIY prefix = "Feature: Sample\nScenario: Sample\n" feature = p.parse_features(prefix + self.file_contents) execute_script(feature, self) except (MissingStepError, AssertionError) as e: self.diagnostic = str(e)
def step_Morelia_evaluates_the_file(self): self.diagnostic = None try: p = Parser() self.file_contents.replace( "\\#", "#" ) # note - this is how to unescape characters - DIY prefix = "Feature: Sample\nScenario: Sample\n" feature = p.parse_features(prefix + self.file_contents) execute_script(feature, self) except (MissingStepError, AssertionError) as e: self.diagnostic = str(e)
def step_a_file_contains_statements_produce_diagnostics_(self, statements, diagnostics): r'a file contains (.+), it produces (.+)' try: statements = statements.replace('\\n', '\n') statements = statements.replace('\\', '') language = self._get_language() p = Parser(language=language).parse_features(statements) p.evaluate(self) raise Exception('we expect syntax errors here') # pragma: nocover except (SyntaxError, AssertionError) as e: e = e.args[0] self.assert_regex_contains(re.escape(diagnostics), e)
def step_Morelia_evaluates_the_file(self): self.diagnostic = None try: language = self._get_language() p = Parser(language=language) self.file_contents.replace( '\\#', '#') # note - this is how to unescape characters - DIY prefix = u'{}: Sample\n{}: Sample\n'.format( self.feature_keyword, self.scenario_keyword) p.parse_features(prefix + self.file_contents).evaluate(self) except (MissingStepError, AssertionError) as e: self.diagnostic = str(e)
def step_a_file_contains_statements_produce_diagnostics_( self, statements, diagnostics): r'a file contains (.+), it produces (.+)' try: statements = statements.replace('\\n', '\n') statements = statements.replace('\\', '') language = self._get_language() p = Parser(language=language).parse_features(statements) p.evaluate(self) raise Exception('we expect syntax errors here') # pragma: nocover except (SyntaxError, AssertionError) as e: e = e.args[0] self.assert_regex_contains(re.escape(diagnostics), e)
def test_fail_informatively_on_bad_scenario_regex(self): filename = os.path.join(pwd, 'features/scenario_matching.feature') self._matching_pattern = '\\' with self.assertRaises(SyntaxError): self._ast = Parser().parse_file(filename, scenario=self._matching_pattern)
def run(filename, suite, as_str=None, scenario=r".*", verbose=False, show_all_missing=True, **kwargs): # NOQA """Parse file and run tests on given suite. :param str filename: file name :param unittest.TestCase suite: TestCase instance :param string as_str: None to use file or a string containing the feature to parse :param string scenario: a regex pattern to match the scenario to run :param boolean verbose: be verbose :param boolean show_all_missing: show all missing steps """ formatter = kwargs.get("formatter", None) if verbose and not formatter: if has_color_support(): formatter = ColorTextFormatter() else: formatter = PlainTextFormatter() kwargs["formatter"] = formatter kwargs["show_all_missing"] = show_all_missing if as_str is None: source = File(filename) else: source = Text(as_str, filename) feature = Parser().parse_features(source) return execute_script(feature, suite, scenario=scenario, **kwargs)
def test_record_filename(self): filename = features_dir / "morelia.feature" feature = Parser().parse_features(File(filename)) assert feature.__class__ == Feature assert str(filename) == feature.filename step = feature.steps[3].steps[1] assert str(filename) == step.get_filename()
def test_deal_with_pesky_carriage_returns( self): # because Morse Code will live forever! source = "Given a string with spacies and \r\n another string " steps = Parser().parse_feature(source) step = steps[0] assert isinstance(step, Given) assert step.predicate == "a string with spacies and\nanother string"
def test_step_multiline_predicate(self): feature = '%s multiline predicate' % self.when_keyword language = self._get_language() steps = Parser(language=language).parse_feature(feature) matcher = self._get_default_machers() visitor = TestVisitor(self, matcher, NullFormatter()) visitor.visit(steps[0])
def test_given_a_string_with_given_in_it(self): source = "Given a string with Given in it \nAnd another string" steps = Parser().parse_feature(source) # ^ note the spacies step = steps[0] assert isinstance(step, Given) assert (step.predicate == "a string with Given in it" ) # <-- note spacies are gone
def test_two_dimensional_table_reconstruction(self): language = self._get_language() p = Parser(language=language).parse_features( self.assemble_short_scene_table()) step = p.steps[0].steps[0].steps[0] self.assertEqual(step.keyword + ': ' + step.predicate, step.reconstruction().strip())
def test_language_directive(self): input = '# language: pl\n%s: prevent wild animals from eating us' % self.feature_keyword steps = Parser().parse_feature(input) step = steps[0] assert step.__class__ == Feature self.assertEqual(step.keyword, self.feature_keyword) self.assertEqual(step.predicate, 'prevent wild animals from eating us')
def test___scenario(self): input = ' %s: with spacies' % self.scenario_keyword language = self._get_language() steps = Parser(language=language).parse_feature(input) step = steps[0] assert step.__class__ == Scenario self.assertEqual(step.keyword, self.scenario_keyword) self.assertEqual(step.predicate, 'with spacies')
def test_feature(self): language = self._get_language() input = '%s: prevent wild animals from eating us' % self.feature_keyword steps = Parser(language=language).parse_feature(input) step = steps[0] assert step.__class__ == Feature self.assertEqual(step.keyword, self.feature_keyword) self.assertEqual(step.predicate, 'prevent wild animals from eating us')
def test_given_a_string_with_a_line_breaker_followed_by_a_keyword(self): source = "Given a string \\\n And another string" steps = Parser().parse_feature(source) assert 1 == len(steps) step = steps[0] assert isinstance(step, Given) assert step.source == "Given a string \\\n And another string" assert step.predicate == "a string \\\n And another string"
def test_feature_with_lone_comment(self): input = 'i be a newbie feature' language = self._get_language() p = Parser(language=language) try: p.parse_feature(input) assert False # should fail! # pragma: nocover except SyntaxError as e: e = e.args[0] try: feature_name = TRANSLATIONS[language].get('feature', self.feature_keyword) except KeyError: feature_name = self.feature_keyword else: feature_name = feature_name.replace('|', ' or ') self.assert_regex_contains(r'feature files must start with a %s' % feature_name, e)
def test_record_filename(self): language = self._get_language() filename = pwd + '/features/morelia%s.feature' % (language or '') thang = Parser(language=language).parse_file(filename) feature = thang.steps[0] assert feature.__class__ == Feature assert feature.filename == filename step = feature.steps[3].steps[1] assert filename == step.get_filename()
def test_two_dimensional_table(self): global elements, factions elements = [] factions = [] language = self._get_language() Parser(language=language).parse_features( self.assemble_short_scene_table()).evaluate(self) self.assertEqual([['Pangolin', 'Glyptodon'], ['Pangea', 'Laurasia']], [factions, elements])
def test_given_a_broken_string_with_excess_spacies(self): input = '%s a string with spacies and \n another string ' % self.given_keyword language = self._get_language() steps = Parser(language=language).parse_feature(input) step = steps[0] assert step.__class__ == Given self.assertEqual(step.keyword, self.given_keyword) self.assertEqual(step.predicate, 'a string with spacies and\nanother string')
def test_should_only_run_matching_scenarios(self): filename = os.path.join(pwd, 'features/scenario_matching.feature') self._matching_pattern = r'Scenario Matches [12]' self._ast = Parser().parse_file(filename, scenario=self._matching_pattern) scenario_matcher_re = re.compile(self._matching_pattern) for included_scenario in self._ast.steps[0].steps: self.assertIsNotNone( scenario_matcher_re.match(included_scenario.predicate))
def test_deal_with_pesky_carriage_returns( self): # because Morse Code will live forever! input = '%s a string with spacies and \r\n another string ' % self.given_keyword language = self._get_language() steps = Parser(language=language).parse_feature(input) step = steps[0] assert step.__class__ == Given self.assertEqual(step.keyword, self.given_keyword) self.assertEqual(step.predicate, 'a string with spacies and\nanother string')
def test_file_without_feature_defined(self): input = 'i be a newbie feature' language = self._get_language() p = Parser(language=language) try: p.parse_feature(input) assert False # should fail! # pragma: nocover except SyntaxError as e: e = e.args[0] try: feature_name = TRANSLATIONS[language].get( 'feature', self.feature_keyword) except KeyError: feature_name = self.feature_keyword else: feature_name = feature_name.replace('|', ' or ') self.assert_regex_contains( r'feature files must start with a %s' % feature_name, e)
def test_scenario_with_steps_is_parsed(self): scenario = self.__sample_scenario() steps = Parser().parse_feature(scenario) scenario, given_step, and_step, when_step, then_step = steps assert scenario.predicate == "See all vendors" assert (given_step.predicate == "I am logged in as a user in the administrator role") assert and_step.predicate == "There are 3 vendors" assert when_step.predicate == "I go to the manage vendors page" assert then_step.predicate == "I should see the first 3 vendor names"
def test_feature_with_scenario(self): source = """Feature: Civi-lie-zation Scenario: starz upon tharz bucks""" steps = Parser().parse_feature(source) step = steps[0] assert isinstance(step, Feature) assert step.predicate == "Civi-lie-zation" step = steps[1] assert isinstance(step, Scenario) assert step.predicate == "starz upon tharz bucks"
def test_feature_with_long_comment(self): # ERGO how to detect shadowed test cases?? language = self._get_language() p = Parser(language=language) input = '''%s: The Sacred Giant Mosquito of the Andes # at http://www.onagocag.com/nazbird.jpg so pay no attention to the skeptics!''' % self.feature_keyword try: p.parse_feature(input) assert False # should raise a SyntaxError # pragma: nocover except SyntaxError as e: self.assert_regex_contains('linefeed in comment', str(e)) self.assert_regex_contains('line 2', str(e)) steps = p.steps assert steps[0].__class__ == Feature step = steps[1] assert step.__class__ == Comment self.assertEqual(step.keyword, '#')
def test_feature_with_long_comment( self): # ERGO how to detect shadowed test cases?? language = self._get_language() p = Parser(language=language) input = '''%s: The Sacred Giant Mosquito of the Andes # at http://www.onagocag.com/nazbird.jpg so pay no attention to the skeptics!''' % self.feature_keyword try: p.parse_feature(input) assert False # should raise a SyntaxError # pragma: nocover except SyntaxError as e: self.assert_regex_contains('linefeed in comment', str(e)) self.assert_regex_contains('line 2', str(e)) steps = p.steps assert steps[0].__class__ == Feature step = steps[1] assert step.__class__ == Comment self.assertEqual(step.keyword, '#')
def test_given_a_string_with_a_line_breaker_followed_by_a_keyword(self): input = '%(given)s a string \\\n And another string' % { 'given': self.given_keyword, 'and': self.and_keyword, } language = self._get_language() steps = Parser(language=language).parse_feature(input) assert 1 == len(steps) step = steps[0] assert step.__class__ == Given self.assertEqual(step.keyword, self.given_keyword) self.assertEqual(step.predicate, 'a string \\\n And another string')
def test_another_two_dimensional_table(self): global crunks, zones crunks = [] zones = [] scene = self.assemble_scene_table_source( 'Step my milkshake brings all the boys to the yard\n') language = self._get_language() Parser(language=language).parse_features(scene).evaluate(self) self.assertEqual(['work', 'mall', 'jail', 'work', 'mall', 'jail'], crunks) self.assertEqual( ['beach', 'beach', 'beach', 'hotel', 'hotel', 'hotel'], zones)
def step_a_file_contains_statements_produce_diagnostics_( self, statements, diagnostics): r"a file contains (.+), it produces (.+)" try: statements = statements.replace("\\n", "\n") statements = statements.replace("\\", "") feature = Parser().parse_features(statements) execute_script(feature, self) raise Exception("we expect syntax errors here") # pragma: nocover except (SyntaxError, AssertionError) as e: e = e.args[0] self.assert_regex_contains(re.escape(diagnostics), e)
def test_given_a_string_with_given_in_it(self): input = '%(given)s a string with Given in it \n%(and)s another string' % { 'given': self.given_keyword, 'and': self.and_keyword, } language = self._get_language() steps = Parser(language=language).parse_feature( input) # ^ note the spacies step = steps[0] assert step.__class__ == Given self.assertEqual(step.keyword, self.given_keyword) self.assertEqual( step.predicate, 'a string with Given in it') # <-- note spacies are gone
def test_format_faults_like_python_errors(self): language = self._get_language() filename = pwd + '/features/morelia%s.feature' % (language or '') thang = Parser(language=language).parse_file(filename) step = thang.steps[0].steps[3].steps[1] assert filename == step.get_filename() omen = 'The Alpine glaciers move' diagnostic = step.format_fault(omen) parent_reconstruction = step.parent.reconstruction().strip('\n') reconstruction = step.reconstruction() expect = '\n File "%s", line %s, in %s\n %s\n%s' % \ (step.get_filename(), step.line_number, parent_reconstruction, reconstruction, omen) assert expect == diagnostic
def test_feature_with_scenario(self): input = '''%(feature)s: Civi-lie-zation %(scenario)s: starz upon tharz bucks''' % { 'feature': self.feature_keyword, 'scenario': self.scenario_keyword, } language = self._get_language() steps = Parser(language=language).parse_feature(input) step = steps[0] assert step.__class__ == Feature self.assertEqual(step.keyword, self.feature_keyword) self.assertEqual(step.predicate, 'Civi-lie-zation') step = steps[1] assert step.__class__ == Scenario self.assertEqual(step.keyword, self.scenario_keyword) self.assertEqual(step.predicate, 'starz upon tharz bucks')
def test_labels(self): filename = os.path.join(pwd, 'features/labels.feature') ast = Parser().parse_file(filename) ast.evaluate(self, show_all_missing=True)
def test_many_test_methods(self): """Check setUp/tearDown when many tests in one TestCase.""" filename = os.path.join(pwd, 'features/setupteardown.feature') ast = Parser().parse_file(filename) ast.evaluate(self, show_all_missing=True)
def test_setup_teardown(self): """Check for multiple setUp/tearDown calls.""" filename = os.path.join(pwd, 'features/setupteardown.feature') ast = Parser().parse_file(filename) ast.evaluate(self, show_all_missing=True)
def test_docstrings_should_be_passed_as_text_to_step(self): filename = os.path.join(pwd, 'features/docstrings.feature') ast = Parser().parse_file(filename) ast.evaluate(self, show_all_missing=True)
class InfoOnAllFailingScenariosTest(TestCase): def test_should_report_on_all_failing_scenarios(self): self._add_failure_pattern = re.compile('Scenario: Add two numbers\n\s*Then the result should be "120" on the screen\n\s*.*AssertionError:\s*70 != 120', re.DOTALL) self._substract_failure_pattern = re.compile('Scenario: Subtract two numbers\n\s*Then the result should be "80" on the screen\n\s*.*AssertionError:\s*70 != 80', re.DOTALL) self._multiply_failure_pattern = re.compile('Scenario: Multiply two numbers\n\s*Then the result should be "12" on the screen\n\s*.*AssertionError:\s*3 != 12', re.DOTALL) self._division_failure_pattern = re.compile('Scenario: Divide two numbers\n\s*Then the result should be "4" on the screen\n\s*.*AssertionError:\s*2 != 4', re.DOTALL) filename = os.path.join(pwd, 'features/info_on_all_failing_scenarios.feature') ast = Parser().parse_file(filename) ast.evaluate(self) def step_feature_with_number_scenarios_has_been_described_in_file(self, feature_file): r'that feature with 4 scenarios has been described in file "([^"]+)"' filename = os.path.join(pwd, 'features/{}'.format(feature_file)) self._ast = Parser().parse_file(filename) def step_that_test_case_passing_number_and_number_scenario_and_failing_number_and_number_has_been_written(self): r'that test case passing 1 and 3 scenario and failing 2 and 4 has been written' class _EvaluatedTestCase(SampleTestCaseMixIn, TestCase): def step_I_press_subtract(self): pass def step_I_press_divide(self): pass self._evaluated_test_case = _EvaluatedTestCase self._failing_patterns = [ self._substract_failure_pattern, self._division_failure_pattern ] def step_that_test_case_failing_all_scenarios_been_written(self): r'that test case failing all scenarios been written' class _EvaluatedTestCase(SampleTestCaseMixIn, TestCase): def step_I_press_add(self): pass def step_I_press_subtract(self): pass def step_I_press_multiply(self): pass def step_I_press_divide(self): pass self._evaluated_test_case = _EvaluatedTestCase self._failing_patterns = [ self._add_failure_pattern, self._substract_failure_pattern, self._multiply_failure_pattern, self._division_failure_pattern ] def step_that_test_case_passing_number_number_and_number_scenario_and_failing_number_has_been_written(self): r'that test case passing 2, 3 and 4 scenario and failing 1 has been written' class _EvaluatedTestCase(SampleTestCaseMixIn, TestCase): def step_I_press_add(self): pass self._evaluated_test_case = _EvaluatedTestCase self._failing_patterns = [ self._add_failure_pattern, ] def step_that_test_case_passing_all_scenarios_been_written(self): r'that test case passing all scenarios been written' class _EvaluatedTestCase(SampleTestCaseMixIn, TestCase): pass self._evaluated_test_case = _EvaluatedTestCase def step_that_test_case_failing_number_number_and_number_scenario_and_passing_number_has_been_written(self): r'that test case failing 1, 2 and 3 scenario and passing 4 has been written' class _EvaluatedTestCase(SampleTestCaseMixIn, TestCase): def step_I_press_add(self): pass def step_I_press_subtract(self): pass def step_I_press_multiply(self): pass self._evaluated_test_case = _EvaluatedTestCase self._failing_patterns = [ self._add_failure_pattern, self._substract_failure_pattern, self._multiply_failure_pattern, ] def step_I_run_test_case(self): r'I run test case' self._catch_exception = None try: tc = self._evaluated_test_case() self._ast.evaluate(tc) except Exception as e: self._catch_exception = e # warning: possible leak, use with caution def step_I_will_get_assertion_error_with_information_number_scenarios_passed_number_scenarios_failed(self, message): r'I will get assertion error with information "([^"]+)"' message = self._catch_exception.args[0] self.assertTrue(message.startswith(message)) def step_I_will_get_traceback_of_each_failing_scenario(self): r'I will get traceback of each failing scenario' patterns = self._failing_patterns message = self._catch_exception.args[0] for pattern in patterns: self.assertRegexpMatches(message, pattern) def step_I_won_t_get_assertion_error(self): r'I won\'t get assertion error' self.assertIsNone(self._catch_exception)
def test_evaluate_file(self): language = self._get_language() thang = Parser(language=language).parse_file(pwd + '/features/morelia%s.feature' % (language or '')) thang.evaluate(self)
def assemble_scene_table(self, moar=''): scene = self.assemble_scene_table_source(moar) language = self._get_language() p = Parser(language=language) self.table_scene = p.parse_features(scene)
def test_parse_feature_Row(self): language = self._get_language() p = Parser(language=language) p.parse_feature(''' | piggy | op |''') assert Row == p.steps[0].__class__ assert p.steps[0].predicate == 'piggy | op |'
def step_feature_with_number_scenarios_has_been_described_in_file(self, feature_file): r'that feature with 4 scenarios has been described in file "([^"]+)"' filename = os.path.join(pwd, 'features/{}'.format(feature_file)) self._ast = Parser().parse_file(filename)