def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ started_at = datetime.now() self.loader.find_and_load_step_definitions() call_hook('before', 'all') results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if not features_files: self.output.print_no_features_found(self.loader.base_dir) return failed = False try: for filename in features_files: feature = Feature.from_file(filename) results.append(feature.run(self.scenarios)) except exceptions.LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True
def test_feature_loaded_from_file_sets_step_line_and_step_filenames(): "Feature.from_file sets StepDescription into Scenario objects, " \ "giving line number and filename as well" feature_file = cjoin('1st_feature_dir', 'one_more.feature') feature = Feature.from_file(feature_file) (scenario, ) = feature.scenarios step1, step2, step3, step4 = scenario.steps for step in scenario.steps: assert_equals(step.described_at.file, fs.relpath(feature_file)) assert_equals(step1.sentence, "* I have entered 10 into the calculator") assert_equals(step1.described_at.line, 7) assert_equals(step2.sentence, "* I have entered 4 into the calculator") assert_equals(step2.described_at.line, 8) assert_equals(step3.sentence, "* I press multiply") assert_equals(step3.described_at.line, 9) assert_equals(step4.sentence, "* the result should be 40 on the screen") assert_equals(step4.described_at.line, 10)
def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ started_at = datetime.now() self.loader.find_and_load_step_definitions() call_hook('before', 'all') results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if not features_files: self.output.print_no_features_found(self.loader.base_dir) return failed = False try: for filename in features_files: feature = Feature.from_file(filename) results.append(feature.run(self.scenarios)) except LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True
def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if self.random: random.shuffle(features_files) if not features_files: self.output.print_no_features_found(self.loader.base_dir) return # only load steps if we've located some features. # this prevents stupid bugs when loading django modules # that we don't even want to test. try: self.loader.find_and_load_step_definitions() except StepLoadingError as e: print("Error loading step definitions:\n", e) return call_hook('before', 'all') failed = False try: for filename in features_files: feature = Feature.from_file(filename) results.append( feature.run(self.scenarios, tags=self.tags, random=self.random, failfast=self.failfast)) except exceptions.LettuceSyntaxError as e: sys.stderr.write(e.msg) failed = True except: if not self.failfast: e = sys.exc_info()[1] print("Died with %s" % str(e)) traceback.print_exc() else: print("Lettuce aborted running any more tests " "because was called with the `--failfast` option") failed = True finally: total = TotalResult(results) total.output_format() call_hook('after', 'all', total) if failed: raise SystemExit(2) return total
def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ self.loader.find_and_load_step_definitions() for callback in CALLBACK_REGISTRY['all']['before']: callback() results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if not features_files: self.output.print_no_features_found(self.loader.base_dir) return try: for filename in features_files: feature = Feature.from_file(filename) results.append(feature.run()) except LettuceSyntaxError, e: sys.stderr.write(e.msg) raise SystemExit(2)
def test_feature_loaded_from_file_sets_step_line_and_step_filenames(): "Feature.from_file sets StepDescription into Scenario objects, " \ "giving line number and filename as well" feature_file = cjoin('1st_feature_dir', 'one_more.feature') feature = Feature.from_file(feature_file) (scenario, ) = feature.scenarios step1, step2, step3, step4 = scenario.steps for step in scenario.steps: assert_equals(step.described_at.file, fs.relpath(feature_file)) assert_equals(step1.sentence, "* I have entered 10 into the calculator") assert_equals(step1.described_at.line, 7) assert_equals(step2.sentence, "* I have entered 4 into the calculator") assert_equals(step2.described_at.line, 8) assert_equals(step3.sentence, "* I press multiply") assert_equals(step3.described_at.line, 9) assert_equals(step4.sentence, "* the result should be 40 on the screen") assert_equals(step4.described_at.line, 10)
def test_scenario_representation_without_colors(): "Scenario represented without colors" feature_file = ojoin('runner_features', 'first.feature') feature = Feature.from_file(feature_file) assert_equals( feature.scenarios[0].represented(), " Scenario: Do nothing # tests/functional/output_features/runner_features/first.feature:6\n" )
def test_scenario_outline_representation_without_colors(): "Scenario Outline represented without colors" feature_file = ojoin('..', 'simple_features', '1st_feature_dir', 'some.feature') feature = Feature.from_file(feature_file) assert_equals( feature.scenarios[0].represented(), " Scenario Outline: Add two numbers # tests/functional/simple_features/1st_feature_dir/some.feature:10\n" )
def test_feature_loaded_from_file_has_feature_line_and_feature_filename(): "Feature.from_file sets FeatureDescription into Feature objects, " "giving line number and filename as well" feature_file = cjoin("1st_feature_dir", "more_features_here", "another.feature") feature = Feature.from_file(feature_file) assert_equals(feature.described_at.file, fs.relpath(feature_file)) assert_equals(feature.described_at.line, 2) assert_equals(feature.name, "Division") assert_equals(feature.described_at.description_at, (3, 4))
def feature_index(request): '''Render the list of lettuce features.''' f_list = [] for path in harvest_lettuces(): if isinstance(path, tuple) and len(path) is 2: path, app_module = path feature_files = fs.FeatureLoader(path).find_feature_files() f_list.extend([Feature.from_file(f) for f in feature_files]) return render_to_response('feature_index.html', {'features': f_list}, context_instance=RequestContext(request))
def test_feature_loaded_from_file_has_feature_line_and_feature_filename(): "Feature.from_file sets FeatureDescription into Feature objects, " \ "giving line number and filename as well" feature_file = cjoin('1st_feature_dir', 'more_features_here', 'another.feature') feature = Feature.from_file(feature_file) assert_equals(feature.described_at.file, fs.relpath(feature_file)) assert_equals(feature.described_at.line, 2) assert_equals(feature.name, 'Division') assert_equals(feature.described_at.description_at, (3, 4))
def test_feature_representation_without_colors(): "Feature represented without colors" feature_file = ojoin('..', 'simple_features', '1st_feature_dir', 'some.feature') feature = Feature.from_file(feature_file) assert_lines( feature.represented(), "Feature: Addition # tests/functional/simple_features/1st_feature_dir/some.feature:5\n" " In order to avoid silly mistakes # tests/functional/simple_features/1st_feature_dir/some.feature:6\n" " As a math idiot # tests/functional/simple_features/1st_feature_dir/some.feature:7\n" " I want to be told the sum of two numbers # tests/functional/simple_features/1st_feature_dir/some.feature:8\n" )
def test_feature_loaded_from_file_sets_scenario_line_and_scenario_filename(): "Feature.from_file sets ScenarioDescription into Scenario objects, " "giving line number and filename as well" feature_file = cjoin("1st_feature_dir", "more_features_here", "another.feature") feature = Feature.from_file(feature_file) scenario1, scenario2 = feature.scenarios assert_equals(scenario1.described_at.file, fs.relpath(feature_file)) assert_equals(scenario1.described_at.line, 6) assert_equals(scenario2.described_at.file, fs.relpath(feature_file)) assert_equals(scenario2.described_at.line, 12)
def test_feature_loaded_from_file_has_description_at(): "Feature.from_file sets FeatureDescription with line numbers of its description" feature_file = cjoin('1st_feature_dir', 'some.feature') feature = Feature.from_file(feature_file) assert_equals(feature.described_at.file, fs.relpath(feature_file)) assert_equals(feature.described_at.line, 5) assert_equals(feature.name, 'Addition') assert_equals(feature.described_at.description_at, (6, 7, 8)) assert_equals( feature.description, "In order to avoid silly mistakes\n" "As a math idiot\n" "I want to be told the sum of two numbers")
def test_feature_loaded_from_file_sets_scenario_line_and_scenario_filename(): "Feature.from_file sets ScenarioDescription into Scenario objects, " \ "giving line number and filename as well" feature_file = cjoin('1st_feature_dir', 'more_features_here', 'another.feature') feature = Feature.from_file(feature_file) scenario1, scenario2 = feature.scenarios assert_equals(scenario1.described_at.file, fs.relpath(feature_file)) assert_equals(scenario1.described_at.line, 6) assert_equals(scenario2.described_at.file, fs.relpath(feature_file)) assert_equals(scenario2.described_at.line, 12)
def test_feature_loaded_from_file_has_description_at(): "Feature.from_file sets FeatureDescription with line numbers of its description" feature_file = cjoin("1st_feature_dir", "some.feature") feature = Feature.from_file(feature_file) assert_equals(feature.described_at.file, fs.relpath(feature_file)) assert_equals(feature.described_at.line, 5) assert_equals(feature.name, "Addition") assert_equals(feature.described_at.description_at, (6, 7, 8)) assert_equals( feature.description, "In order to avoid silly mistakes\n" "As a math idiot\n" "I want to be told the sum of two numbers", )
def test_feature_loaded_from_file_has_feature_line_and_feature_filename(): """ Feature.from_file sets FeatureDescription into Feature objects, giving line number and filename as well """ feature_file = cjoin('1st_feature_dir', 'more_features_here', 'another.feature') feature = Feature.from_file(feature_file) assert_equals(feature.described_at.file, fs.relpath(feature_file)) assert_equals(feature.described_at.line, 2) assert_equals(feature.name, 'Division') assert_equals(feature.described_at.description_at, (3, 4))
def test_undefined_step_represent_string(): "Undefined step represented without colors" feature_file = ojoin('runner_features', 'first.feature') feature = Feature.from_file(feature_file) step = feature.scenarios[0].steps[0] assert_equals( step.represent_string(step.sentence), " Given I do nothing # tests/functional/output_features/runner_features/first.feature:7\n" ) assert_equals( step.represent_string("foo bar"), " foo bar # tests/functional/output_features/runner_features/first.feature:7\n" )
def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if self.random: random.shuffle(features_files) if not features_files: self.output.print_no_features_found(self.loader.base_dir) return world.port_number = 8181 # only load steps if we've located some features. # this prevents stupid bugs when loading django modules # that we don't even want to test. try: self.loader.find_and_load_step_definitions() except StepLoadingError as e: print "Error loading step definitions:\n", e return call_hook('before', 'all') call_hook('before', 'batch') begin_time = datetime.utcnow() failed = False try: for filename in features_files: feature = Feature.from_file(filename) results.append( feature.run(self.scenarios, tags=self.tags, random=self.random, failfast=self.failfast)) except exceptions.LettuceSyntaxError as e: sys.stderr.write(e.msg) failed = True except exceptions.NoDefinitionFound, e: sys.stderr.write(e.msg) failed = True
def test_defined_step_represent_string(): "Defined step represented without colors" feature_file = ojoin('runner_features', 'first.feature') feature_dir = ojoin('runner_features') loader = FeatureLoader(feature_dir) world._output = StringIO() world._is_colored = False loader.find_and_load_step_definitions() feature = Feature.from_file(feature_file) step = feature.scenarios[0].steps[0] step.run(True) assert_equals( step.represent_string(step.sentence), " Given I do nothing # tests/functional/output_features/runner_features/dumb_steps.py:6\n" )
def test_feature_finder_loads_feature_objects(): "Feature.from_file loads feature by filename" feature_file = cjoin("1st_feature_dir", "more_features_here", "another.feature") feature = Feature.from_file(feature_file) assert_equals(type(feature), Feature) expected_scenario_names = ["Regular numbers", "Fractions"] got_scenario_names = [s.name for s in feature.scenarios] assert_equals(expected_scenario_names, got_scenario_names) assert_equals(len(feature.scenarios[0].steps), 4) step1, step2, step3, step4 = feature.scenarios[0].steps assert_equals(step1.sentence, "* I have entered 3 into the calculator") assert_equals(step2.sentence, "* I have entered 2 into the calculator") assert_equals(step3.sentence, "* I press divide") assert_equals(step4.sentence, "* the result should be 1.5 on the screen")
def test_feature_finder_loads_feature_objects(): "Feature.from_file loads feature by filename" feature_file = cjoin('1st_feature_dir', 'more_features_here', 'another.feature') feature = Feature.from_file(feature_file) assert_equals(type(feature), Feature) expected_scenario_names = ["Regular numbers", "Fractions"] got_scenario_names = [s.name for s in feature.scenarios] assert_equals(expected_scenario_names, got_scenario_names) assert_equals(len(feature.scenarios[0].steps), 4) step1, step2, step3, step4 = feature.scenarios[0].steps assert_equals(step1.sentence, '* I have entered 3 into the calculator') assert_equals(step2.sentence, '* I have entered 2 into the calculator') assert_equals(step3.sentence, '* I press divide') assert_equals(step4.sentence, '* the result should be 1.5 on the screen')
def worker_process(args): self, filename = args sys.stdout = StringIO() sys.stderr = StringIO() failed = False results = [] try: self.output call_hook('before', 'all') feature = Feature.from_file(filename) results.append( feature.run(self.scenarios, tags=self.tags, random=self.random, failfast=self.failfast)) except exceptions.LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True
def worker_process(args): self, filename = args sys.stdout = StringIO() sys.stderr = StringIO() failed = False results = [] try: self.output call_hook('before', 'all') feature = Feature.from_file(filename) results.append( feature.run(self.scenarios, tags=self.tags, random=self.random, failfast=self.failfast)) except exceptions.LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True
class Runner(object): """ Main lettuce's test runner Takes a base path as parameter (string), so that it can look for features and step definitions on there. """ def __init__(self, base_path, scenarios=None, verbosity=0, enable_xunit=False, xunit_filename=None): """ lettuce.Runner will try to find a terrain.py file and import it from within `base_path` """ self.single_feature = None if os.path.isfile(base_path) and os.path.exists(base_path): self.single_feature = base_path base_path = os.path.dirname(base_path) sys.path.insert(0, base_path) self.loader = fs.FeatureLoader(base_path) self.verbosity = verbosity self.scenarios = scenarios and map(int, scenarios.split(",")) or None sys.path.remove(base_path) if verbosity is 0: from lettuce.plugins import non_verbose as output elif verbosity is 1: from lettuce.plugins import dots as output elif verbosity is 2: from lettuce.plugins import scenario_names as output elif verbosity is 3: from lettuce.plugins import shell_output as output else: from lettuce.plugins import colored_shell_output as output if enable_xunit: xunit_output.enable(filename=xunit_filename) reload(output) self.output = output def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ started_at = datetime.now() try: self.loader.find_and_load_step_definitions() except StepLoadingError, e: print "Error loading step definitions:\n", e return call_hook('before', 'all') results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if not features_files: self.output.print_no_features_found(self.loader.base_dir) return failed = False try: for filename in features_files: feature = Feature.from_file(filename) results.append(feature.run(self.scenarios)) except exceptions.LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True
class ParallelRunner(Runner): def __init__(self, base_path, scenarios=None, verbosity=0, random=False, enable_xunit=False, xunit_filename=None, enable_subunit=False, subunit_filename=None, tags=None, failfast=False, auto_pdb=False, smtp_queue=None, workers=None): super(ParallelRunner, self).__init__(base_path, scenarios=scenarios, verbosity=verbosity, random=random, enable_xunit=enable_xunit, xunit_filename=xunit_filename, enable_subunit=enable_subunit, subunit_filename=subunit_filename, failfast=failfast, auto_pdb=auto_pdb, tags=tags) self.workers = workers def sort_scenarios(self, scenarios_to_run): # sort scenarios in slowest to fastest by looking at the last run time if existed if os.path.isfile('.scenarios.csv'): scenario_metas = csv.DictReader(open(".scenarios.csv")) name_duration_dict = dict() for scenario_meta in scenario_metas: name_duration_dict[ scenario_meta['name']] = scenario_meta['duration'] scenario_duration_dict = dict() for scenario in scenarios_to_run: if scenario.name in name_duration_dict: scenario_duration_dict[scenario] = name_duration_dict[ scenario.name] else: scenario_duration_dict[scenario] = 0 # now sort them: sorted_tupples = sorted(scenario_duration_dict.items(), key=lambda x: -int(x[1])) scenarios_to_run = [tupple[0] for tupple in sorted_tupples] return scenarios_to_run def collate_results(self, results): feature_results = [] for feature, scenario_results in itertools.groupby( results, lambda r: r[0].scenario.feature): all_results = [] for results in scenario_results: for result in results: all_results.append(result) feature_results.append(FeatureResult(feature, *list(all_results))) return feature_results def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ failed = False begin_time = datetime.utcnow() try: self.loader.find_and_load_step_definitions() except StepLoadingError, e: print "Error loading step definitions:\n", e return if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if self.random: random.shuffle(features_files) if not features_files: self.output.print_no_features_found(self.loader.base_dir) return def process_scenarios(scenario_queue, port_number, results, errors, interupted_event): # print "running batch with port number: {}".format(port_number) world.port_number = port_number call_hook('before', 'batch') while scenario_queue and not interupted_event.is_set(): try: scenario_to_execute = scenario_queue.pop(0) ignore_case = True result = scenario_to_execute.run(ignore_case, failfast=self.failfast) results.append(result) except pickle.PicklingError: print( "Pickling Error -- probably due to step functions having the same name." ) print() if result: print " Result: {}".format(result) import StringIO class MyPickler(pickle.Pickler): """Custom Picklier to give more detail on whats messing things up """ def save(self, obj): print(' pickling object', obj, 'of type', type(obj)) pickle.Pickler.save(self, obj) stringIO = StringIO.StringIO() pickler = MyPickler(stringIO) pickler.save(result) else: print " No Result" except Exception as e: print "Died with %s" % str(e) traceback.print_exc() errors.append(e) call_hook('after', 'batch') scenarios_to_run = [] try: for filename in features_files: feature = Feature.from_file(filename) feature_scenarios_to_run = feature.scenarios_to_run( self.scenarios, self.tags) scenarios_to_run.extend(feature_scenarios_to_run) except exceptions.LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True
call_hook('before', 'all') results = [] if len(self.feature_files) == 0: self.feature_files = self.loader.find_feature_files() if not self.feature_files: self.output.print_no_features_found(self.loader.base_dir) return failed = False try: for filename in self.feature_files: feature = Feature.from_file(filename) result = feature.run(self.scenarios, tags=self.tags) results.append( result ) if self.abort_fail and not result.passed: break except exceptions.LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True except: e = sys.exc_info()[1] print "Died with %s" % str(e) traceback.print_exc() failed = True finally:
class Runner(object): """ Main lettuce's test runner Takes a base path as parameter (string), so that it can look for features and step definitions on there. """ def __init__(self, base_path, scenarios=None, verbosity=0, no_color=False, random=False, enable_xunit=False, xunit_filename=None, enable_subunit=False, subunit_filename=None, tags=None, failfast=False, auto_pdb=False, smtp_queue=None): """ lettuce.Runner will try to find a terrain.py file and import it from within `base_path` """ self.tags = tags self.single_feature = None if os.path.isfile(base_path) and os.path.exists(base_path): self.single_feature = base_path base_path = os.path.dirname(base_path) sys.path.insert(0, base_path) self.loader = fs.FeatureLoader(base_path) self.verbosity = verbosity self.scenarios = scenarios and map(int, scenarios.split(",")) or None self.failfast = failfast if auto_pdb: autopdb.enable(self) sys.path.remove(base_path) if verbosity is 0: from lettuce.plugins import non_verbose as output elif verbosity is 1: from lettuce.plugins import dots as output elif verbosity is 2: from lettuce.plugins import scenario_names as output else: if verbosity is 4: from lettuce.plugins import colored_shell_output as output msg = ('Deprecated in lettuce 2.2.21. Use verbosity 3 without ' '--no-color flag instead of verbosity 4') warnings.warn(msg, DeprecationWarning) elif verbosity is 3: if no_color: from lettuce.plugins import shell_output as output else: from lettuce.plugins import colored_shell_output as output self.random = random if enable_xunit: xunit_output.enable(filename=xunit_filename) if smtp_queue: smtp_mail_queue.enable() if enable_subunit: subunit_output.enable(filename=subunit_filename) reload(output) self.output = output def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if self.random: random.shuffle(features_files) if not features_files: self.output.print_no_features_found(self.loader.base_dir) return # only load steps if we've located some features. # this prevents stupid bugs when loading django modules # that we don't even want to test. try: self.loader.find_and_load_step_definitions() except StepLoadingError, e: print "Error loading step definitions:\n", e return call_hook('before', 'all') failed = False try: for filename in features_files: feature = Feature.from_file(filename) results.append( feature.run(self.scenarios, tags=self.tags, random=self.random, failfast=self.failfast)) except exceptions.LettuceSyntaxError, e: sys.stderr.write(e.msg) failed = True
def run(self): """ Find and load step definitions, and them find and load features under `base_path` specified on constructor """ CALLBACK_REGISTRY.clear(name='output') CALLBACK_REGISTRY.clear(name='common_output') if self.verbosity is 0: from lettuce.plugins import non_verbose as output elif self.verbosity is 1: from lettuce.plugins import dots as output elif self.verbosity is 2: from lettuce.plugins import scenario_names as output elif self.verbosity is 3: from lettuce.plugins import shell_output as output else: from lettuce.plugins import colored_shell_output as output reload(output) self.output = output results = [] if self.single_feature: features_files = [self.single_feature] else: features_files = self.loader.find_feature_files() if self.random: random.shuffle(features_files) if not features_files: self.output.print_no_features_found(self.loader.base_dir) return # only load steps if we've located some features. # this prevents stupid bugs when loading django modules # that we don't even want to test. try: self.loader.find_and_load_step_definitions() except StepLoadingError as e: print "Error loading step definitions:\n", e raise SystemExit(3) failed = False try: call_hook('before', 'all') for filename in features_files: feature = Feature.from_file(filename) results.append( feature.run(self.scenarios, tags=self.tags, random=self.random, failfast=self.failfast)) except exceptions.LettuceSyntaxError as e: sys.stderr.write(e.msg) failed = True except exceptions.FailFast: print print ("Lettuce aborted running any more tests " "because was called with the `--failfast` option") failed = True except Exception: # ensure our output is undiverted sys.stdout = real_stdout print "Exception in Lettuce itself!" failed = True raise except BaseException: failed = True raise finally: total = TotalResult(results) total.output_format() call_hook('after', 'all', total) if not total.passed: failed = True if failed: raise SystemExit(2) return total