Пример #1
0
    def run(self):
        """Runs the current test case. 

        Steps taken to run test are

        1. Create empty step context
        2. Load first step
        3. Update context for current step
        4. Run middlewares for 'BEFORE_STEP'
        5. Dispatch step to middlewares
        6. Run middlewares for 'AFTER_STEP'
        7. Update current Step
        8. Go to step 3. Unless last step
        
        Raises:
            ImproperlyConfigured -- If the test is not ready, this is raised
        """

        if not self.ready():
            raise ImproperlyConfigured(
                "Cannot start testcase because the test is not ready")

        step_context = StepContext(self)

        while self.current_step is not None:  # End condition when no more steps
            # Step 1. Update context
            step_context.update_context(self.current_step, step_context)

            # Step 2. Run middlewares for `before_step`
            self.run_middlewares(step_context, MIDDLEWARE_MODE_BEFORE_STEP)

            # Step 3. Run Step
            try:
                self.execute_step(step_context)
            except Exception as e:
                step_context.step_settings["Exception"] = e
                self.run_middlewares(step_context,
                                     MIDDLEWARE_MODE_STEP_FAILURE)
                break

            # Step 4. Run middleswares for `after_step`
            self.run_middlewares(step_context, MIDDLEWARE_MODE_AFTER_STEP)

            # Step 5. Update step
            self.current_step = step_context.next_step

        # Prepare TearDown Steps
        self.current_step = self.tear_down_first_step

        # Step 6. Run TearDown steps
        while self.current_step is not None:
            step_context.update_context(self.current_step, step_context)
            self.run_middlewares(step_context,
                                 MIDDLEWARE_MODE_TEARDOWN_BEFORE_STEP)
            self.execute_step(step_context)
            self.run_middlewares(step_context,
                                 MIDDLEWARE_MODE_TEARDOWN_AFTER_STEP)
            self.current_step = step_context.next_step
Пример #2
0
    def _get_step_result_by_tag(self, first_step, tag):
        current_step = first_step
        while True:
            tag_value = getattr(current_step, "tag", None)
            if tag_value == tag:
                return lambda: current_step.get_result()

            if current_step.is_last_step():
                break
            current_step = current_step.next_step
        raise ImproperlyConfigured(f"No step found with tag {tag}")
Пример #3
0
    def execute_step(self, step_context):
        action_interface = step_context.action_interface

        # If a step has a defined interface or not
        if action_interface is None:
            for interface in self.interfaces:  # Go through each interface
                try:
                    self.interfaces[interface].dispatch(step_context)
                    break
                except ImproperlyConfigured:  # Interface does not define action
                    continue
            else:
                raise ImproperlyConfigured(
                    f"No interface found that defines {step_context.step_action}"
                )
        else:
            if action_interface not in self.interfaces:
                raise ImproperlyConfigured(
                    f"Interface {action_interface} is not installed")
            self.interfaces[action_interface].dispatch(step_context)
Пример #4
0
    def load_testloader(self, loader_name, loader_module) -> None:
        loader_path = ".".join([loader_module, "loader_entry"])
        loader_entry = load_module(loader_path)

        loader = load_module(loader_entry)()

        if not isinstance(loader, TBBaseTestLoader):
            raise ImproperlyConfigured(
                "TestLoader is not of instance TBBaseTestLoader")

        self.testloaders[loader_name] = loader
Пример #5
0
    def load_objectmap_parser(self, parser_name, parser_module) -> None:
        parser_path = ".".join([parser_module, "objectmap_parser_entry"])
        parser_entry = load_module(parser_path)

        parser = load_module(parser_entry)()

        if not isinstance(parser, TBBaseObjectMapParser):
            raise ImproperlyConfigured(
                "Objectmap parser is not of instance TBBaseObjectMapParser")

        self.objectmap_parsers[parser_name] = parser
Пример #6
0
    def load_middleware(self, middleware_name, middleware_module) -> None:
        middleware_path = ".".join([middleware_module, "middleware_entry"])
        middleware_entry = load_module(middleware_path)

        middleware = load_module(middleware_entry)

        if not issubclass(middleware, TBBaseMiddleware):
            raise ImproperlyConfigured(
                "Middleware does not derive from TBBaseMiddleware")

        self.middlewares[middleware_name] = middleware
Пример #7
0
    def load_interface(self, interface_name, interface_module) -> None:
        interface_path = ".".join([interface_module, "interface_entry"])
        interface_entry = load_module(interface_path)

        interface = load_module(interface_entry)

        if not issubclass(interface, TBBaseInterface):
            raise ImproperlyConfigured(
                "Interface does not derive from TBBaseInterface")

        self.interfaces[interface_name] = interface
Пример #8
0
    def load_object_map(self, object_map, object_map_name) -> None:
        """Registers an objectmap for the test
        
        Arguments:
            object_map {TBBaseObjectMap} -- The objectmap instance
            object_map_name {str} -- Name of the objectmap
        """

        if not isinstance(object_map, TBBaseObjectMap):
            raise ImproperlyConfigured(
                "Objectmap is not of instance TBBaseObjectMap")

        self.object_maps[object_map_name] = object_map
Пример #9
0
    def load_middleware(self, middleware) -> None:
        """Creates and appends middleware to list of middleswares.

        Note that the order in which this function is called has a role in how the script may run.
        
        Arguments:
            middleware {TBBaseMiddleware} -- Class of TBMiddlware, **not instance of**
        """

        if not issubclass(middleware, TBBaseMiddleware):
            raise ImproperlyConfigured(
                "Middleware is not of subclass TBBaseMiddleware")
        self.middlewares.append(middleware())  # Create and append middleware
Пример #10
0
    def create_tests(self, test_location, loader_name, profile_name):
        if loader_name not in self.testloaders:
            raise ImproperlyConfigured(
                f"No testloader installed named {loader_name}")
        if profile_name not in self.profiles:
            raise ImproperlyConfigured(
                f"No profile installed named {profile_name}")

        # Returns a list of tests from file
        tests = self.testloaders[loader_name].load_tests(test_location)

        for test in tests:
            profile = self.profiles[profile_name]

            ## Step 1. Load middlewares
            if "middlewares" in profile:
                for middleware_name in profile["middlewares"]:
                    middleware = self.middlewares[middleware_name]
                    test.load_middleware(middleware)

            ## Step 2. Load interfaces
            for interface_name, interface in self.interfaces.items():
                test.load_interface(interface, interface_name)

            ## Step 3. Load objectmap
            for objectmap_name in settings["OBJECT_MAPS"]:
                obj_parser_name, obj_location = settings["OBJECT_MAPS"][
                    objectmap_name]

                if obj_parser_name not in self.objectmap_parsers:
                    raise ImproperlyConfigured(
                        f"ObjectMap Parser {obj_parser_name} is not installed")

                obj_parser = self.objectmap_parsers[obj_parser_name]
                object_map = obj_parser.parse(objectmap_name, obj_location)

                test.load_object_map(object_map, objectmap_name)

        return tests
Пример #11
0
    def load_interface(self, interface, interface_name) -> None:
        """Creates and registers a interface for the test
        
        Arguments:
            interface {TBBaseInterface} -- Class of TBBaseInterface, **not instance of**
            interface_name {String} -- Name of the interface
        Raises:
            ImproperlyConfigured -- Raised if interface not of subclass TBBaseInterface
        """

        if not issubclass(interface, TBBaseInterface):
            raise ImproperlyConfigured(
                "Interface is not of subclass TBBaseInterface")
        self.interfaces[interface_name] = interface(
        )  # Create and register interface
Пример #12
0
    def _step_field_from_fixture(self, field, test):
        _, _, fixture_info = field.partition(".")

        f0 = fixture_info.find('[')

        fixture_name = fixture_info[0:f0]
        fixture_column = fixture_info[f0 + 2:-2]

        fixture = test.fixtures.get(fixture_name)

        if fixture is None:
            raise ImproperlyConfigured(
                f"Test does not contain fixture{fixture_name}")

        return lambda: fixture.get_value(test.get_current_iteration(),
                                         fixture_column)
Пример #13
0
    def load_fixtures(self, fixture, fixture_name=None):
        """Load fixture to testcase
        
        Arguments:
            fixture {TBBaseFixture} -- Fixture instance
        
        Keyword Arguments:
            fixture_name {str} -- Optional name of fixture (default: {None})
        
        Raises:
            ImproperlyConfigured -- Raised if fixture is not of subclass TBBaseFixture
        """

        if not isinstance(fixture, TBBaseFixture):
            raise ImproperlyConfigured(
                "Expected 'fixture' to be of class TBBaseFixture")

        if fixture_name is None:
            self.fixtures[fixture.fixture_name] = fixture
        else:
            self.fixtures[fixture_name] = fixture
Пример #14
0
    def dispatch(self, step_context):
        """Attempts to dispatch a action to the interface
        
        Arguments:
            step_context {StepContext} -- The current step context
        
        Raises:
            ImproperlyConfigured -- Raised if interface does not define the action specified by `step_context.step_action`
        """

        action = step_context.step_action
        defined_action_words = self.get_list_of_action_words()

        if action in defined_action_words:
            try:
                getattr(self, action)(step_context) # Run step
                self._pass_step(step_context) # Mark step as passed
            except Exception as e:
                self._fail_step(step_context, e) # Mark step as failed
                raise
        else:
            raise ImproperlyConfigured(f"Interface does not have a defined action {action}")
Пример #15
0
    def load_tests(self, test_location) -> List[TBBaseTest]:
        """Parse and add a test to tests
        
        Arguments:
            path {str} -- The path to the yaml test case
        """
        if not os.path.exists(test_location):
            raise ImproperlyConfigured(f"Path does not exist: {test_location}")

        yaml_test_data = None
        with open(test_location) as f:
            yaml_test_data = yaml.load(f)

        # Check that test steps exists
        test_steps = yaml_test_data.get("steps")
        if not test_steps:
            raise ImproperlyConfigured("Testcase has no steps, stopping")

        # Create base test with properties
        test_properties = yaml_test_data.get(
            "properties", {})  # Load property mapping, or empty dict type
        test = TBBaseTest(**test_properties)  # load all properties to test

        # Load all additional properties to testcase
        test_additional_properties = yaml_test_data.get(
            "additional_properties")
        if test_additional_properties:
            for setting in test_additional_properties:  # Add all settings to testcase
                value = test_additional_properties[setting]
                test.load_additional_property(setting, value)

        # Load test fixtures
        test_fixtures = yaml_test_data.get("fixtures")
        if test_fixtures:
            for fixture_name in test_fixtures:  # Iterate over each fixture in testcase
                fixture_path = test_fixtures[fixture_name]

                if not os.path.exists(
                        fixture_path):  #If fixture is relative path
                    fixture_path = os.path.join(
                        os.path.dirname(test_location),  # Testcase path
                        fixture_path  # Fixture path relative to testcase
                    )
                fixture = CSVFixture(fixture_name,
                                     fixture_path)  # Create fixutre

                test.load_fixtures(fixture)  # Load fixture in test

        first_step = None
        _cur_step = None

        # Load test steps
        for i, step in enumerate(test_steps):
            if i == 0:  # First step
                first_step = self.load_test_step(step, test)
                _cur_step = first_step
                continue
            next_step = self.load_test_step(step, test,
                                            first_step)  # Load the next step
            _cur_step.add_next_step(next_step)  # Register the next step
            _cur_step = next_step  # Replace current step with next step

        test.load_steps(first_step)

        # Load teardown steps
        tear_down_steps = yaml_test_data.get("tear_down")
        first_step = None
        _cur_step = None

        # Load test steps
        if tear_down_steps is not None:
            for i, step in enumerate(tear_down_steps):
                if i == 0:  # First step
                    first_step = self.load_test_step(step, test)
                    _cur_step = first_step
                    continue
                next_step = self.load_test_step(
                    step, test, first_step)  # Load the next step
                _cur_step.add_next_step(next_step)  # Register the next step
                _cur_step = next_step  # Replace current step with next step

            test.load_tear_down_steps(first_step)

        return [test]