def console_writer_after_each_step(self, step): """ Writes the step to the console after it was run :param Step step: the step to write to the console """ if not isinstance(step.parent.parent, Feature): return color_func = self.get_color_func(step.state) line_jump_seq = self.get_line_jump_seq() * ( ((len(step.raw_text) + 3) if step.text else 1) + (len(step.table) if step.table else 0)) output = u"{0} {1}{2}".format( line_jump_seq, self.get_id_sentence_prefix(step, colorful.bold_cyan), color_func(step.sentence)) if step.text: id_padding = self.get_id_padding(len(step.parent.steps)) output += colorful.bold_white( u'\n {0}"""'.format(id_padding)) output += colorful.cyan(u"".join([ "\n {0}{1}".format(id_padding, l) for l in step.raw_text ])) output += colorful.bold_white( u'\n {0}"""'.format(id_padding)) if step.table: colored_pipe = colorful.bold_white("|") col_widths = self.get_table_col_widths(step.table) for row in step.table: output += u"\n {0} {1} {0}".format( colored_pipe, (" {0} ").format(colored_pipe).join( color_func(u"{1: <{0}}".format(col_widths[i], x)) for i, x in enumerate(row))) if step.state == step.State.FAILED: if world.config.with_traceback: output += u"\n {0}{1}".format( self.get_id_padding(len(step.parent.steps) - 2), "\n ".join([ colorful.red(l) for l in step.failure.traceback.split("\n")[:-2] ])) output += u"\n {0}{1}: {2}".format( self.get_id_padding(len(step.parent.steps) - 2), colorful.bold_red(step.failure.name), colorful.red(step.failure.reason)) write(output)
def output_failure(step_func, errors): """ Write the given errors to stdout. """ sys.stdout.write(colorful.bold_red('✘')) if step_func is not None: sys.stdout.write( colorful.red(' (at {0})'.format(get_func_location(step_func)))) sys.stdout.write('\n') for error in errors: print(colorful.red(' - {0}'.format(error)))
def main(): cmd = "ls" if len(argv) > 1: cmd = argv[1] t = GitCommands() if hasattr(t, "cmd_%s" % cmd): ret = False try: ret = getattr(t, "cmd_%s" % cmd)(argv[2:]) except TesseraError, e: stderr.write(colorful.bold_red("Error:") + " %s\n" % colorful.red(e)) exit(0 if ret else 1)
def main(): cmd = "ls" if len(argv) > 1: cmd = argv[1] t = GitCommands() if hasattr(t, "cmd_%s" % cmd): ret = False try: ret = getattr(t, "cmd_%s" % cmd)(argv[2:]) except TesseraError, e: stderr.write( colorful.bold_red("Error:") + " %s\n" % colorful.red(e)) exit(0 if ret else 1)
def console_writer_after_each_scenario(self, scenario): """ If the scenario is a ExampleScenario it will write the Examples header :param Scenario scenario: the scenario which was ran. """ output = "" if isinstance(scenario, ScenarioOutline): output += u"\n {0}:\n".format(colorful.bold_white(scenario.example_keyword)) output += colorful.bold_white(u" {0}| {1} |".format( self.get_id_padding(len(scenario.scenarios)), u" | ".join("{1: <{0}}".format(scenario.get_column_width(i), x) for i, x in enumerate(scenario.examples_header)) )) elif isinstance(scenario, ScenarioLoop): output += u"\n {0}: {1}".format(colorful.bold_white(scenario.iterations_keyword), colorful.cyan(scenario.iterations)) elif isinstance(scenario.parent, ScenarioOutline): colored_pipe = colorful.bold_white("|") color_func = self.get_color_func(scenario.state) output += u"{0} {1}{2} {3} {2}".format( self.get_line_jump_seq(), self.get_id_sentence_prefix(scenario, colorful.bold_cyan, len(scenario.parent.scenarios)), colored_pipe, (u" {0} ").format(colored_pipe).join( color_func(u"{1: <{0}}".format(scenario.parent.get_column_width(i), x)) for i, x in enumerate(scenario.example.data) ) ) if scenario.state == Step.State.FAILED: failed_step = scenario.failed_step if world.config.with_traceback: output += u"\n {0}{1}".format(self.get_id_padding(len(scenario.parent.scenarios)), "\n ".join([colorful.red(l) for l in failed_step.failure.traceback.split("\n")[:-2]])) output += u"\n {0}{1}: {2}".format(self.get_id_padding(len(scenario.parent.scenarios)), colorful.bold_red(failed_step.failure.name), colorful.red(failed_step.failure.reason)) elif isinstance(scenario.parent, ScenarioLoop): colored_pipe = colorful.bold_white("|") color_func = self.get_color_func(scenario.state) output += u"{0} {1}{2} {3: <18} {2}".format(self.get_line_jump_seq(), self.get_id_sentence_prefix(scenario, colorful.bold_cyan, len(scenario.parent.scenarios)), colored_pipe, color_func(scenario.iteration)) if scenario.state == Step.State.FAILED: failed_step = scenario.failed_step if world.config.with_traceback: output += u"\n {0}{1}".format(self.get_id_padding(len(scenario.parent.scenarios)), "\n ".join([colorful.red(l) for l in failed_step.failure.traceback.split("\n")[:-2]])) output += u"\n {0}{1}: {2}".format(self.get_id_padding(len(scenario.parent.scenarios)), colorful.bold_red(failed_step.failure.name), colorful.red(failed_step.failure.reason)) if output: write(output)
def console_writer_after_each_step(self, step): """ Writes the step to the console after it was run :param Step step: the step to write to the console """ if not isinstance(step.parent.parent, Feature): return color_func = self.get_color_func(step.state) line_jump_seq = self.get_line_jump_seq() * (((len(step.raw_text) + 3) if step.text else 1) + (len(step.table) if step.table else 0)) output = u"{0} {1}{2}".format(line_jump_seq, self.get_id_sentence_prefix(step, colorful.bold_cyan), color_func(step.sentence)) if step.text: id_padding = self.get_id_padding(len(step.parent.steps)) output += colorful.bold_white(u'\n {0}"""'.format(id_padding)) output += colorful.cyan(u"".join(["\n {0}{1}".format(id_padding, l) for l in step.raw_text])) output += colorful.bold_white(u'\n {0}"""'.format(id_padding)) if step.table: colored_pipe = colorful.bold_white("|") col_widths = self.get_table_col_widths(step.table) for row in step.table: output += u"\n {0} {1} {0}".format(colored_pipe, (" {0} ").format(colored_pipe).join( color_func(u"{1: <{0}}".format(col_widths[i], x)) for i, x in enumerate(row) )) if step.state == step.State.FAILED: if world.config.with_traceback: output += u"\n {0}{1}".format(self.get_id_padding(len(step.parent.steps) - 2), "\n ".join([colorful.red(l) for l in step.failure.traceback.split("\n")[:-2]])) output += u"\n {0}{1}: {2}".format(self.get_id_padding(len(step.parent.steps) - 2), colorful.bold_red(step.failure.name), colorful.red(step.failure.reason)) write(output)
def write_error(text): """ Writes the given text to the console """ write("{}: {}".format(colorful.bold_red("Error"), colorful.red(text)))
def console_writer_after_each_scenario(self, scenario): """ If the scenario is a ExampleScenario it will write the Examples header :param Scenario scenario: the scenario which was ran. """ output = "" if isinstance(scenario, ScenarioOutline): output += u"\n {0}:\n".format( colorful.bold_white(scenario.example_keyword)) output += colorful.bold_white(u" {0}| {1} |".format( self.get_id_padding(len(scenario.scenarios), offset=2), u" | ".join("{1: <{0}}".format(scenario.get_column_width(i), x) for i, x in enumerate(scenario.examples_header)))) elif isinstance(scenario, ScenarioLoop): output += u"\n {0}: {1}".format( colorful.bold_white(scenario.iterations_keyword), colorful.cyan(scenario.iterations)) elif isinstance(scenario.parent, ScenarioOutline): colored_pipe = colorful.bold_white("|") color_func = self.get_color_func(scenario.state) output += u"{0} {1}{2} {3} {2}".format( self.get_line_jump_seq(), self.get_id_sentence_prefix(scenario, colorful.bold_cyan, len(scenario.parent.scenarios)), colored_pipe, (u" {0} ").format(colored_pipe).join( color_func(u"{1: <{0}}".format( scenario.parent.get_column_width(i), x)) for i, x in enumerate(scenario.example.data))) if scenario.state == Step.State.FAILED: failed_step = scenario.failed_step if world.config.with_traceback: output += u"\n {0}{1}".format( self.get_id_padding(len(scenario.parent.scenarios)), "\n ".join([ colorful.red(l) for l in failed_step.failure.traceback.split("\n")[:-2] ])) output += u"\n {0}{1}: {2}".format( self.get_id_padding(len(scenario.parent.scenarios)), colorful.bold_red(failed_step.failure.name), colorful.red(failed_step.failure.reason)) elif isinstance(scenario.parent, ScenarioLoop): colored_pipe = colorful.bold_white("|") color_func = self.get_color_func(scenario.state) output += u"{0} {1}{2} {3: <18} {2}".format( self.get_line_jump_seq(), self.get_id_sentence_prefix(scenario, colorful.bold_cyan, len(scenario.parent.scenarios)), colored_pipe, color_func(scenario.iteration)) if scenario.state == Step.State.FAILED: failed_step = scenario.failed_step if world.config.with_traceback: output += u"\n {0}{1}".format( self.get_id_padding(len(scenario.parent.scenarios)), "\n ".join([ colorful.red(l) for l in failed_step.failure.traceback.split("\n")[:-2] ])) output += u"\n {0}{1}: {2}".format( self.get_id_padding(len(scenario.parent.scenarios)), colorful.bold_red(failed_step.failure.name), colorful.red(failed_step.failure.reason)) if output: write(output)
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 console_write(self, features, marker): """ Writes the endreport for all features :param list features: all features """ stats = { "features": { "amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0, "pending": 0 }, "scenarios": { "amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0, "pending": 0 }, "steps": { "amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0, "pending": 0 }, } pending_steps = [] duration = timedelta() for feature in features: if not feature.has_to_run(world.config.scenarios, world.config.feature_tags, world.config.scenario_tags): continue stats["features"]["amount"] += 1 stats["features"][feature.state] += 1 if feature.state in [Step.State.PASSED, Step.State.FAILED]: duration += feature.duration for scenario in feature.all_scenarios: if not scenario.has_to_run(world.config.scenarios, world.config.feature_tags, world.config.scenario_tags): continue if isinstance(scenario, ScenarioOutline): # skip ScenarioOutlines continue if isinstance(scenario, ScenarioLoop): # skip ScenarioLoop continue stats["scenarios"]["amount"] += 1 stats["scenarios"][scenario.state] += 1 for step in scenario.steps: stats["steps"]["amount"] += 1 stats["steps"][step.state] += 1 if step.state == Step.State.PENDING: pending_steps.append(step) colored_closing_paren = colorful.bold_white(")") colored_comma = colorful.bold_white(", ") passed_word = colorful.bold_green("{0} passed") failed_word = colorful.bold_red("{0} failed") skipped_word = colorful.cyan("{0} skipped") pending_word = colorful.bold_brown("{0} pending") output = colorful.bold_white("{0} features (".format( stats["features"]["amount"])) output += passed_word.format(stats["features"]["passed"]) if stats["features"]["failed"]: output += colored_comma + failed_word.format( stats["features"]["failed"]) if stats["features"]["skipped"]: output += colored_comma + skipped_word.format( stats["features"]["skipped"]) if stats["features"]["pending"]: output += colored_comma + pending_word.format( stats["features"]["pending"]) output += colored_closing_paren output += "\n" output += colorful.bold_white("{} scenarios (".format( stats["scenarios"]["amount"])) output += passed_word.format(stats["scenarios"]["passed"]) if stats["scenarios"]["failed"]: output += colored_comma + failed_word.format( stats["scenarios"]["failed"]) if stats["scenarios"]["skipped"]: output += colored_comma + skipped_word.format( stats["scenarios"]["skipped"]) if stats["scenarios"]["pending"]: output += colored_comma + pending_word.format( stats["scenarios"]["pending"]) output += colored_closing_paren output += "\n" output += colorful.bold_white("{} steps (".format( stats["steps"]["amount"])) output += passed_word.format(stats["steps"]["passed"]) if stats["steps"]["failed"]: output += colored_comma + failed_word.format( stats["steps"]["failed"]) if stats["steps"]["skipped"]: output += colored_comma + skipped_word.format( stats["steps"]["skipped"]) if stats["steps"]["pending"]: output += colored_comma + pending_word.format( stats["steps"]["pending"]) output += colored_closing_paren if pending_steps: sr = StepRegistry() pending_step_implementations = make_unique_obj_list( pending_steps, lambda x: x.definition_func) output += colorful.white( "\nYou have {0} pending step implementation{1} affecting {2} step{3}:\n {4}\n\nNote: this could be the reason for some failing subsequent steps" .format( len(pending_step_implementations), "s" if len(pending_step_implementations) is not 1 else "", len(pending_steps), "s" if len(pending_steps) is not 1 else "", "\n ".join([ "- '{0}' @ {1}".format( sr.get_pattern(s.definition_func), get_func_code(s.definition_func).co_filename) for s in pending_step_implementations ]))) output += "\n" output += colorful.cyan( "Run {0} finished within {1}:{2} minutes".format( marker, int(duration.total_seconds()) / 60, duration.total_seconds() % 60.0)) write(output)
def console_write_after_all(features, marker): """ Writes the endreport for all features :param list features: all features """ stats = { "features": {"amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0}, "scenarios": {"amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0}, "steps": {"amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0}, } duration = timedelta() for feature in features: stats["features"]["amount"] += 1 stats["features"][feature.state] += 1 if feature.state in [Step.State.PASSED, Step.State.FAILED]: duration += feature.duration for scenario in feature.all_scenarios: if isinstance(scenario, ScenarioOutline): # skip ScenarioOutlines continue stats["scenarios"]["amount"] += 1 stats["scenarios"][scenario.state] += 1 for step in scenario.steps: stats["steps"]["amount"] += 1 stats["steps"][step.state] += 1 colored_closing_paren = colorful.bold_white(")") colored_comma = colorful.bold_white(", ") passed_word = colorful.bold_green("{} passed") failed_word = colorful.bold_red("{} failed") skipped_word = colorful.cyan("{} skipped") output = colorful.bold_white("{} features (".format(stats["features"]["amount"])) output += passed_word.format(stats["features"]["passed"]) if stats["features"]["failed"]: output += colored_comma + failed_word.format(stats["features"]["failed"]) if stats["features"]["skipped"]: output += colored_comma + skipped_word.format(stats["features"]["skipped"]) output += colored_closing_paren output += "\n" output += colorful.bold_white("{} scenarios (".format(stats["scenarios"]["amount"])) output += passed_word.format(stats["scenarios"]["passed"]) if stats["scenarios"]["failed"]: output += colored_comma + failed_word.format(stats["scenarios"]["failed"]) if stats["scenarios"]["skipped"]: output += colored_comma + skipped_word.format(stats["scenarios"]["skipped"]) output += colored_closing_paren output += "\n" output += colorful.bold_white("{} steps (".format(stats["steps"]["amount"])) output += passed_word.format(stats["steps"]["passed"]) if stats["steps"]["failed"]: output += colored_comma + failed_word.format(stats["steps"]["failed"]) if stats["steps"]["skipped"]: output += colored_comma + skipped_word.format(stats["steps"]["skipped"]) output += colored_closing_paren output += "\n" output += colorful.cyan("Run {} finished within {}:{} minutes".format(marker, int(duration.total_seconds()) / 60, duration.total_seconds() % 60.0)) write(output)
def console_write(self, features, marker): """ Writes the endreport for all features :param list features: all features """ stats = { "features": {"amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0, "pending": 0}, "scenarios": {"amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0, "pending": 0}, "steps": {"amount": 0, "passed": 0, "failed": 0, "skipped": 0, "untested": 0, "pending": 0}, } pending_steps = [] duration = timedelta() for feature in features: if not feature.has_to_run(world.config.scenarios, world.config.feature_tags, world.config.scenario_tags): continue stats["features"]["amount"] += 1 stats["features"][feature.state] += 1 if feature.state in [Step.State.PASSED, Step.State.FAILED]: duration += feature.duration for scenario in feature.all_scenarios: if not scenario.has_to_run(world.config.scenarios, world.config.feature_tags, world.config.scenario_tags): continue if isinstance(scenario, ScenarioOutline): # skip ScenarioOutlines continue if isinstance(scenario, ScenarioLoop): # skip ScenarioLoop continue stats["scenarios"]["amount"] += 1 stats["scenarios"][scenario.state] += 1 for step in scenario.steps: stats["steps"]["amount"] += 1 stats["steps"][step.state] += 1 if step.state == Step.State.PENDING: pending_steps.append(step) colored_closing_paren = colorful.bold_white(")") colored_comma = colorful.bold_white(", ") passed_word = colorful.bold_green("{0} passed") failed_word = colorful.bold_red("{0} failed") skipped_word = colorful.cyan("{0} skipped") pending_word = colorful.bold_brown("{0} pending") output = colorful.bold_white("{0} features (".format(stats["features"]["amount"])) output += passed_word.format(stats["features"]["passed"]) if stats["features"]["failed"]: output += colored_comma + failed_word.format(stats["features"]["failed"]) if stats["features"]["skipped"]: output += colored_comma + skipped_word.format(stats["features"]["skipped"]) if stats["features"]["pending"]: output += colored_comma + pending_word.format(stats["features"]["pending"]) output += colored_closing_paren output += "\n" output += colorful.bold_white("{} scenarios (".format(stats["scenarios"]["amount"])) output += passed_word.format(stats["scenarios"]["passed"]) if stats["scenarios"]["failed"]: output += colored_comma + failed_word.format(stats["scenarios"]["failed"]) if stats["scenarios"]["skipped"]: output += colored_comma + skipped_word.format(stats["scenarios"]["skipped"]) if stats["scenarios"]["pending"]: output += colored_comma + pending_word.format(stats["scenarios"]["pending"]) output += colored_closing_paren output += "\n" output += colorful.bold_white("{} steps (".format(stats["steps"]["amount"])) output += passed_word.format(stats["steps"]["passed"]) if stats["steps"]["failed"]: output += colored_comma + failed_word.format(stats["steps"]["failed"]) if stats["steps"]["skipped"]: output += colored_comma + skipped_word.format(stats["steps"]["skipped"]) if stats["steps"]["pending"]: output += colored_comma + pending_word.format(stats["steps"]["pending"]) output += colored_closing_paren if pending_steps: sr = StepRegistry() pending_step_implementations = make_unique_obj_list(pending_steps, lambda x: x.definition_func) output += colorful.white("\nYou have {0} pending step implementation{1} affecting {2} step{3}:\n {4}\n\nNote: this could be the reason for some failing subsequent steps".format( len(pending_step_implementations), "s" if len(pending_step_implementations) is not 1 else "", len(pending_steps), "s" if len(pending_steps) is not 1 else "", "\n ".join(["- '{0}' @ {1}".format(sr.get_pattern(s.definition_func), get_func_code(s.definition_func).co_filename) for s in pending_step_implementations]) )) output += "\n" output += colorful.cyan("Run {0} finished within {1}:{2} minutes".format(marker, int(duration.total_seconds()) / 60, duration.total_seconds() % 60.0)) write(output)
def console_writer_after_each_step(step): """ Writes the step to the console after it was run :param Step step: the step to write to the console """ if not isinstance(step.parent.parent, Feature): return color_func = get_color_func(step.state) line_jump_seq = get_line_jump_seq() * ((len(step.raw_text) + 3) if step.text else 1) output = "{} {}{}".format(line_jump_seq, get_id_sentence_prefix(step, colorful.bold_cyan), color_func(step.sentence)) if step.text: id_padding = get_id_padding(len(step.parent.steps)) output += colorful.bold_white('\n {}"""'.format(id_padding)) output += colorful.cyan("".join(["\n {}{}".format(id_padding, l) for l in step.raw_text])) output += colorful.bold_white('\n {}"""'.format(id_padding)) if step.state == step.State.FAILED: if world.config.with_traceback: output += "\n {}{}".format(get_id_padding(len(step.parent.steps) - 2), "\n ".join([colorful.red(l) for l in step.failure.traceback.split("\n")[:-2]])) output += "\n {}{}: {}".format(get_id_padding(len(step.parent.steps) - 2), colorful.bold_red(step.failure.name), colorful.red(step.failure.reason)) write(output)
def test_step_matches_configs(match_config_files, basedir, cover_min_percentage=None, cover_show_missing=False): """ Test if the given match config files matches the actual matched step implementations. """ if cover_min_percentage is not None and float(cover_min_percentage) > 100: sys.stderr.write( colorful.magenta( 'You are a little cocky to think you can reach a minimum coverage of {0:.2f}%\n' .format(float(cover_min_percentage)))) return 3 # load user's custom python files load_modules(basedir) steps = StepRegistry().steps if not steps: sys.stderr.write( colorful.magenta( 'No step implementations found in {0}, thus doesn\'t make sense to continue' .format(basedir))) return 4 failed = 0 passed = 0 covered_steps = set() for match_config_file in match_config_files: # load the given match config file with codecs.open(match_config_file, "r", "utf-8") as f: match_config = yaml.safe_load(f) if not match_config: print( colorful.magenta( 'No sentences found in {0} to test against'.format( match_config_file))) return 5 else: print( colorful.brown('Testing sentences from {0}:'.format( colorful.bold_brown(match_config_file)))) failed_sentences, passed_senteces = test_step_matches( match_config, steps) failed += failed_sentences passed += passed_senteces covered_steps = covered_steps.union(x['should_match'] for x in match_config) # newline sys.stdout.write('\n') report = colorful.bold_white('{0} sentences ('.format(failed + passed)) if passed > 0: report += colorful.bold_green('{0} passed'.format(passed)) if passed > 0 and failed > 0: report += colorful.bold_white(', ') if failed > 0: report += colorful.bold_red('{0} failed'.format(failed)) report += colorful.bold_white(')') print(report) step_coverage = 100.0 / len(steps) * len(covered_steps) coverage_report = colorful.bold_white( 'Covered {0} of {1} step implementations'.format( len(covered_steps), len(steps))) ret = 0 if failed == 0 else 1 if cover_min_percentage: coverage_color = colorful.bold_green if step_coverage >= float( cover_min_percentage) else colorful.bold_red coverage_report += colorful.bold_white(' (coverage: ') coverage_report += coverage_color('{0:.2f}%'.format(step_coverage)) if float(cover_min_percentage) > step_coverage: coverage_report += colorful.bold_white( ', expected a minimum of {0}'.format( colorful.bold_green(cover_min_percentage + '%'))) if failed == 0: ret = 2 # if tests have passed and coverage is too low we fail with exit code 2 coverage_report += colorful.bold_white(')') print(coverage_report) if cover_show_missing: missing_steps = get_missing_steps(steps, covered_steps) if missing_steps: missing_step_report = colorful.bold_brown('Missing steps:\n') for step in missing_steps: missing_step_report += '- {0} at '.format( colorful.cyan(step[0])) missing_step_report += colorful.cyan(step[1]) + '\n' sys.stdout.write(missing_step_report) return ret
def write_error(text): """ Writes the given text to the console """ write("{0}: {1}".format(colorful.bold_red("Error"), colorful.red(text)))