| # coding=utf-8 |
| """ |
| BDD lettuce framework runner |
| TODO: Support other params (like tags) as well. |
| Supports only 1 param now: folder to search "features" for. |
| """ |
| import _bdd_utils |
| |
| __author__ = 'Ilya.Kazakevich' |
| from lettuce.exceptions import ReasonToFail |
| import sys |
| import lettuce |
| from lettuce import core |
| |
| |
| class _LettuceRunner(_bdd_utils.BddRunner): |
| """ |
| Lettuce runner (BddRunner for lettuce) |
| """ |
| |
| def __init__(self, base_dir, what_to_run): |
| """ |
| |
| :param base_dir base directory to run tests in |
| :type base_dir: str |
| :param what_to_run folder or file to run |
| :type what_to_run str |
| """ |
| super(_LettuceRunner, self).__init__(base_dir) |
| self.__runner = lettuce.Runner(what_to_run) |
| |
| def _get_features_to_run(self): |
| super(_LettuceRunner, self)._get_features_to_run() |
| if self.__runner.single_feature: # We need to run one and only one feature |
| return [core.Feature.from_file(self.__runner.single_feature)] |
| |
| # Find all features in dir |
| features = [] |
| for feature_file in self.__runner.loader.find_feature_files(): |
| feature = core.Feature.from_file(feature_file) |
| assert isinstance(feature, core.Feature), feature |
| # TODO: cut out due to https://github.com/gabrielfalcao/lettuce/issues/451 Fix when this issue fixed |
| feature.scenarios = filter(lambda s: not s.outlines, feature.scenarios) |
| if feature.scenarios: |
| features.append(feature) |
| return features |
| |
| def _run_tests(self): |
| super(_LettuceRunner, self)._run_tests() |
| self.__install_hooks() |
| self.__runner.run() |
| |
| def __step(self, is_started, step): |
| """ |
| Reports step start / stop |
| :type step core.Step |
| :param step: step |
| """ |
| test_name = step.sentence |
| if is_started: |
| self._test_started(test_name, step.described_at) |
| elif step.passed: |
| self._test_passed(test_name) |
| elif step.failed: |
| reason = step.why |
| assert isinstance(reason, ReasonToFail), reason |
| self._test_failed(test_name, message=reason.exception, details=reason.traceback) |
| elif step.has_definition: |
| self._test_skipped(test_name, "In lettuce, we do know the reason", step.described_at) |
| else: |
| self._test_undefined(test_name, step.described_at) |
| |
| def __install_hooks(self): |
| """ |
| Installs required hooks |
| """ |
| |
| # Install hooks |
| lettuce.before.each_feature( |
| lambda f: self._feature_or_scenario(True, f.name, f.described_at)) |
| lettuce.after.each_feature( |
| lambda f: self._feature_or_scenario(False, f.name, f.described_at)) |
| |
| lettuce.before.each_scenario( |
| lambda s: self.__scenario(True, s)) |
| lettuce.after.each_scenario( |
| lambda s: self.__scenario(False, s)) |
| |
| lettuce.before.each_background( |
| lambda b, *args: self._background(True, b.feature.described_at)) |
| lettuce.after.each_background( |
| lambda b, *args: self._background(False, b.feature.described_at)) |
| |
| lettuce.before.each_step(lambda s: self.__step(True, s)) |
| lettuce.after.each_step(lambda s: self.__step(False, s)) |
| |
| def __scenario(self, is_started, scenario): |
| """ |
| Reports scenario launched |
| :type scenario core.Scenario |
| :param scenario: scenario |
| """ |
| if scenario.outlines: |
| scenario.steps = [] # Clear to prevent running. TODO: Fix when this issue fixed |
| scenario.background = None # TODO: undocumented |
| return |
| self._feature_or_scenario(is_started, scenario.name, scenario.described_at) |
| |
| |
| if __name__ == "__main__": |
| (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv) |
| _bdd_utils.fix_win_drive(what_to_run) |
| _LettuceRunner(base_dir, what_to_run).run() |