def test_stepregistry_is_initialized_with_no_step_impls(): """The StepRegistry should be initialized with no registered Step Implementations""" # given & when registry = StepRegistry() # then assert registry.step_implementations() == {}
def test_registering_object(self): """ Test registering object as steps """ registry = StepRegistry() registry.steps.should.be.empty class MySteps(object): ignore = ["no_step_method"] def some_step(step): """When I call some step""" def some_other_step(step): """ Then I expect some behaviour """ def no_step_method(data): """ This is not a step method """ steps_object = MySteps() registry.register_object(steps_object) registry.steps.should.have.length_of(2) registry.steps["When I call some step"].should.be.equal(steps_object.some_step) registry.steps["Then I expect some behaviour"].should.be.equal(steps_object.some_other_step)
def test_registering_object(self): """ Test registering object as steps """ registry = StepRegistry() registry.steps.should.be.empty class MySteps(object): ignore = ["no_step_method"] def some_step(step): """When I call some step""" def some_other_step(step): """ Then I expect some behaviour """ def no_step_method(data): """ This is not a step method """ steps_object = MySteps() registry.register_object(steps_object) registry.steps.should.have.length_of(2) registry.steps["When I call some step"].should.be.equal( steps_object.some_step) registry.steps["Then I expect some behaviour"].should.be.equal( steps_object.some_other_step)
def test_registering_steps_with_gherkin_decorators(self): """ Test registering steps with gherkin specific decorators """ def step_given(): pass def step_when(): pass def step_then(): pass registry = StepRegistry() registry.steps.should.be.empty given(r"I have the number {:g}")(step_given) registry.steps.should.have.length_of(1) registry.steps[r"Given I have the number {:g}"] = step_given # cannot test the when function because sure overwrites it! # stupid stuff # step_when(r"I add \d+ to my number")(step_when) # registry.steps.should.have.length_of(2) # registry.steps[r"When I add \d+ to my number"] = step_when then(re.compile(r"I expect my number to be \d+"))(step_then) registry.steps.should.have.length_of(2)
def test_stepregistry_should_allow_to_register_step_impls(): """The StepRegistry should allow to register a Step Implementation""" # given registry = StepRegistry() # when registry.register("Given", "pattern", None) # then assert registry.step_implementations("Given") == [ StepImpl("Given", "pattern", None) ]
def test_stepregistry_should_create_one_step_decorator_per_keyword(): """The StepRegistry should create one Step decorator for each keyword""" # given registry = StepRegistry() context = {} # when registry.create_step_decorators(context) # then assert len(context) == 4 assert "given" in context assert "when" in context assert "then" in context assert "step" in context
def behave_like(self, sentence): """ Make step behave like another one :param string sentence: the sentence of the step to behave like """ # check if this step has already failed from a previous behave_like call if self.state is Step.State.FAILED: return # create step according to given sentence new_step = Step(None, sentence, self.path, self.line, self.parent, True) merge_step(new_step, StepRegistry().steps) # run or debug step if world.config.debug_steps: new_step.debug() else: new_step.run() # re-raise exception if the failed if new_step.state is Step.State.FAILED: new_step.failure.exception.args = ( "Step '{0}' failed: '{1}'".format( sentence, new_step.failure.exception.message), ) raise new_step.failure.exception
def reset_registries(): """ Fixture to automatically reset singleton registries """ StepRegistry().clear() HookRegistry().reset() ExtensionRegistry().reset()
def tearDown(self): """ Tear down the test Delete all singletons """ StepRegistry().clear() HookRegistry().reset()
def setUp(self): """ Setup test Initialize all singletons """ StepRegistry() return True
def test_stepregistry_step_decorator_should_register_func_with_proper_keyword(keyword): """The StepRegistry should create one Step decorator for each keyword""" # given registry = StepRegistry() context = {} registry.create_step_decorators(context) # when def test_step(): ... test_step = context[keyword.lower()]("pattern")(test_step) # then assert registry.step_implementations(keyword) == [ StepImpl(keyword, "pattern", test_step) ]
def test_stepregitry_step_decorators_for_all_keywords(): """The StepRegistry should return the Step Implementations registered with the ``step`` decorator for all keywords. """ # given registry = StepRegistry() context = {} registry.create_step_decorators(context) # when def test_step(): ... test_step = context["step"]("pattern")(test_step) # then assert registry.step_implementations("Given") == [ StepImpl("Step", "pattern", test_step) ]
def test_registering_steps(self): """ Test registering multiple steps """ registry = StepRegistry() registry.steps.should.be.empty def step_a(): pass def step_b(): pass registry.register("abc", step_a) registry.steps.should.have.length_of(1) registry.steps["abc"].should.be.equal(step_a) registry.register("def", step_b) registry.steps.should.have.length_of(2) registry.steps["def"].should.be.equal(step_b)
def test_registering_same_step(self): """ Test registering step with same regex """ registry = StepRegistry() registry.steps.should.be.empty def step_a(): pass def step_b(): pass registry.register("abc", step_a) registry.steps.should.have.length_of(1) registry.steps["abc"].should.be.equal(step_a) registry.register.when.called_with("abc", step_b).should.throw(SameStepError, "Cannot register step step_b with regex 'abc' because it is already used by step step_a") registry.steps.should.have.length_of(1) registry.steps["abc"].should.be.equal(step_a)
def test_registering_same_step(self): """ Test registering step with same regex """ registry = StepRegistry() registry.steps.should.be.empty def step_a(): pass def step_b(): pass registry.register("abc", step_a) registry.steps.should.have.length_of(1) registry.steps["abc"].should.be.equal(step_a) registry.register.when.called_with("abc", step_b).should.throw( SameStepError, "Cannot register step step_b with regex 'abc' because it is already used by step step_a" ) registry.steps.should.have.length_of(1) registry.steps["abc"].should.be.equal(step_a)
def test_stepregistry_should_gracefully_accept_double_registration(): """ The StepRegistry should gracefully accept a duplicate registration of a Step Implementation """ # given registry = StepRegistry() registry.register("Given", "pattern", None) # when registry.register("Given", "pattern", None) # then assert registry.step_implementations("Given") == [ StepImpl("Given", "pattern", None) ]
def test_registering_steps_with_decorator(self): """ Test registering steps with decorator """ registry = StepRegistry() registry.steps.should.have.length_of(0) def step_a(): pass def step_b(): pass step("abc")(step_a) registry.steps.should.have.length_of(1) registry.steps["abc"].should.be.equal(step_a) step("def")(step_b) registry.steps.should.have.length_of(2) registry.steps["def"].should.be.equal(step_b)
def test_registering_steps(self): """ Test registering multiple steps """ registry = StepRegistry() registry.steps.should.be.empty def step_a(): pass def step_b(): pass registry.register("abc", step_a) registry.steps.should.have.length_of(1) registry.steps["abc"].should.be.equal(step_a) registry.register("def", step_b) registry.steps.should.have.length_of(2) registry.steps["def"].should.be.equal(step_b)
def test_stepregitry_register_func_with_multiple_decorators(): """The StepRegistry should allow a function to be registered with multiple Step decorators""" # given registry = StepRegistry() context = {} registry.create_step_decorators(context) # when def test_step(): ... test_step = context["given"]("pattern")(test_step) test_step = context["when"]("pattern")(test_step) # then assert registry.step_implementations("Given") == [ StepImpl("Given", "pattern", test_step) ] assert registry.step_implementations("When") == [ StepImpl("When", "pattern", test_step) ]
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): 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): 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_yellow("{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" if world.config.wip: if stats["scenarios"]["passed"] > 0: output += colorful.red( "\nThe --wip switch was used, so I didn't expect anything to pass. These scenarios passed:\n" ) has_passed_scenarios = False for feature in features: passed_scenarios = list( filter( lambda s: s.state == Step.State.PASSED, feature.all_scenarios, ) ) for scenario in passed_scenarios: output += colorful.red( "\n - {}: {}".format(feature.path, scenario.sentence) ) has_passed_scenarios = True if has_passed_scenarios: output += "\n" else: output += colorful.green( "\nThe --wip switch was used, so the failures were expected. All is good.\n" ) output += colorful.cyan( "Run {0} finished within {1}".format( marker, humanize.naturaldelta(duration) ) ) 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): 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): 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_yellow("{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" if world.config.wip: if stats["scenarios"]["passed"] > 0: output += colorful.red( "\nThe --wip switch was used, so I didn't expect anything to pass. These scenarios passed:\n" ) has_passed_scenarios = False for feature in features: passed_scenarios = list( filter( lambda s: s.state == Step.State.PASSED, feature.all_scenarios, )) for scenario in passed_scenarios: output += colorful.red("\n - {}: {}".format( feature.path, scenario.sentence)) has_passed_scenarios = True if has_passed_scenarios: output += "\n" else: output += colorful.green( "\nThe --wip switch was used, so the failures were expected. All is good.\n" ) output += colorful.cyan("Run {0} finished within {1}".format( marker, humanize.naturaldelta(duration))) write(output)
def stepregistry(): """ Fixture to create and get a clean StepRegistry instance. """ registry = StepRegistry() yield registry
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 test_step_matches_configs(match_config_files, basedirs, 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( str( 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 for basedir in basedirs: load_modules(basedir) steps = StepRegistry().steps if not steps: sys.stderr.write( str( colorful.magenta( 'No step implementations found in {0}, thus doesn\'t make sense to continue' .format(basedirs)))) 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 print( colorful.yellow('Testing sentences from {0}:'.format( colorful.bold_yellow(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 if 'should_match' in x) # 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_yellow('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 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)