def _build_test_run(self): """Pull all the test plans into a TestRun for eventual execution. Args: None. Returns: None. Raises: :class:`ExecutionError` """ self._test_run = TestRun(self._test_run_config['Description']) for test_plan_config in self._test_plan_configs: self._test_run.add_test_plan(test_plan_config.get_content)
class ExecuteTestRun(object): """This class will parse, validate configurations files necessary for a Bespoke test run. This class is the main access point to executing a test run with Bespoke. Args: bespoke_root |str| = The base path from which Bespoke executes on the server. xsd_path |str| = The absolute path to the XSD folder. global_config_file |str| = The absolute path to the global configuration file. test_run_file |str| = The absolute path to the test run configuration file. resource_config_files <opt>|[str]| = An optional override to use for the resource configuration files (paths must be absolute). test_plan_files <opt>|[str]| = An optional override to use for the test plan file paths (paths must be absolute). tools_config_files <opt>|[str]| = An optional override to use for the tool configuration file paths (paths must be absolute). build_config_files <opt>|[str]| = An optional override to use for the build configuration file paths (paths must be absolute). Raises: :class:`ExecutionError` = Could not load configuration files for a variety of reasons. """ def __init__(self, bespoke_root, xsd_path, global_config_file, test_run_file, resource_config_files=[], test_plan_files=[], tools_config_files=[], build_config_files=[]): ## init ## self._bespoke_root = bespoke_root self._xsd_path = xsd_path self._global_config_file = global_config_file #Path must be absolute. self._test_run_file = test_run_file self._resource_config_files = resource_config_files self._test_plan_files = test_plan_files self._tools_config_files = tools_config_files self._build_config_files = build_config_files ## XSD ## self._global_xsd_path = join(self._xsd_path, GLOBAL_CONFIG_XSD) self._test_run_xsd_path = join(self._xsd_path, TEST_RUN_CONFIG_XSD) self._resource_xsd_path = join(self._xsd_path, RESOURCE_CONFIG_XSD) self._build_xsd_path = join(self._xsd_path, BUILD_CONFIG_XSD) self._tool_xsd_path = join(self._xsd_path, TOOL_CONFIG_XSD) self._test_plan_xsd_path = join(self._xsd_path, TEST_PLAN_XSD) ## delayed init ## self._config_path = '' self._test_run_path = '' self._test_plan_path = '' self._test_script_path = '' self._resources = {} #A merged dictionary of ResourceConfig content. self._global_config = None self._test_run_config = None self._builds = {} self._tools = {} self._test_plan_configs = [] self._test_run = None ## load ## self._load_global() self._load_resources() self._load_test_run() self._load_builds() self._load_tools() self._load_test_plans() ## finalize test run ## self._build_test_run() def _build_test_run(self): """Pull all the test plans into a TestRun for eventual execution. Args: None. Returns: None. Raises: :class:`ExecutionError` """ self._test_run = TestRun(self._test_run_config['Description']) for test_plan_config in self._test_plan_configs: self._test_run.add_test_plan(test_plan_config.get_content) def _load_builds(self): """Parse and load the build configuration files. Args: None. Returns: None. Raises: :class:`ExecutionError` """ #A list of BuildConfig content dictionaries. tmp_builds = [] try: for config in self._build_config_files: tmp_builds.append(BuildConfig(config, self._build_xsd_path, 'Build').get_content) except ConfigError as e: err = "Failure to load Build config file '{0}': {1}".format(e._config_file, e.msg) raise ExecutionError(err) if len(tmp_builds) == 0: self._builds = {} elif len(tmp_builds) > 1: try: self._builds = merge_dictionaries(tmp_builds, fail_on_duplicates=True) except KeyError as e: raise ExecutionError("Duplicate build names detected in build " "configuration files: {}", e) else: self._builds = tmp_builds[0] def _load_global(self): """Parse and load the global configuration file. Args: None. Returns: None. Raises: :class:`ExecutionError` """ try: self._global_config = GlobalConfig(self._global_config_file, self._global_xsd_path) except ConfigError as e: err = "Failure to load Global config file '{0}': {1}".format(e._config_file, e.msg) raise ExecutionError(err) #Determine paths for other configuration files. self._config_path = self._global_config['ConfigPath'] self._test_run_path = self._global_config['TestRunPath'] self._test_plan_path = self._global_config['TestPlanPath'] self._test_script_path = self._global_config['TestScriptPath'] #Parse and load the resource paths if no overrides are specified. if len(self._resource_config_files) == 0: for config in self._global_config['ResourceConfigs']: self._resource_config_files.append(join(self._config_path, config)) #Populate Bespoke Global Environment BespokeGlobals.ABS_LOCAL_RESULTS = self._global_config['ResultsPath'] BespokeGlobals.ABS_LOCAL_TESTS = self._test_script_path BespokeGlobals.ABS_LOCAL_TOOLS = self._global_config['ToolPath'] BespokeGlobals.BESPOKE_SERVER_HOSTNAME = self._global_config['BespokeServerHostname'] def _load_resources(self): """Parse and load the resource configuration file. Args: None. Returns: None. Raises: :class:`ExecutionError` """ #A list of ResourceConfig content dictionaries. tmp_resources = [] try: for config in self._resource_config_files: tmp_resources.append(ResourceConfig(config, self._resource_xsd_path).get_content) except ConfigError as e: err = "Failure to load Resource config file '{0}': {1}".format(e._config_file, e.msg) raise ExecutionError(err) if len(tmp_resources) > 1: try: self._resources = merge_dictionaries(tmp_resources, fail_on_duplicates=True) except KeyError as e: raise ExecutionError("Duplicate aliases detected in resource " "configuration files: {}", e) else: self._resources = tmp_resources[0] def _load_test_run(self): """Parse and load the test run configuration file. Args: None. Returns: None. Raises: :class:`ExecutionError` """ try: self._test_run_config = TestRunConfig(join(self._test_run_path, self._test_run_file), self._test_run_xsd_path) except ConfigError as e: err = "Failure to load Test Run config file '{0}': {1}".format(e._config_file, e.msg) raise ExecutionError(err) #Parse and load the tool config paths if no overrides are specified. if len(self._tools_config_files) == 0: for config in self._test_run_config['ToolConfigs']: self._tools_config_files.append(join(self._config_path, config)) #Parse and load the build config paths if no overrides are specified. if len(self._build_config_files) == 0: for config in self._test_run_config['BuildConfigs']: self._build_config_files.append(join(self._config_path, config)) #Parse and load the test plan paths if no overrides are specified. if len(self._test_plan_files) == 0: for config in self._test_run_config['TestPlans']: self._test_plan_files.append(join(self._test_plan_path, config)) def _load_test_plans(self): """Parse and load the test plan configuration files. Args: None. Returns: None. Raises: :class:`ExecutionError` """ try: for config in self._test_plan_files: self._test_plan_configs.append(TestPlanConfig(config, self._test_plan_xsd_path, self._builds, self._tools, self._resources)) except ConfigError as e: err = "Failure to load Test Plan file '{0}': {1}".format(e._config_file, e.msg) raise ExecutionError(err) def _load_tools(self): """Parse and load the tool configuration files. Args: None. Returns: None. Raises: :class:`ExecutionError` """ #A list of BuildConfig content dictionaries. tmp_tools = [] try: for config in self._tools_config_files: tmp_tools.append(ToolConfig(config, self._build_xsd_path, 'Tool').get_content) except ConfigError as e: err = "Failure to load Tool config file '{0}': {1}".format(e._config_file, e.msg) raise ExecutionError(err) if len(tmp_tools) == 0: self._tools = {} elif len(tmp_tools) > 1: try: self._tools = merge_dictionaries(tmp_tools, fail_on_duplicates=True) except KeyError as e: raise ExecutionError("Duplicate tool names detected in tool " "configuration files: {}", e) else: self._tools = tmp_tools[0] def execute_test_run(self): """Execute the TestRun. Args: None. Returns: None. Raises: :class:`FatalError`: Fatal error occurred and unreliable results possibly recorded. :class:`Failure`: The TestRun failed during execution. """ self._test_run.execute() @property def builds(self): """A dictionary of Build objects. Returns: |{str::class:`Build`}| """ return self._builds @property def global_config(self): """The GlobalConfig for this test run. Returns: |:class:`GlobalConfig`| = This looks like a dictionary. """ return self._global_config @property def resources(self): """A dictionary of resources. Returns: |{str::class:`SystemUnderTest`}| """ return self._test_run_config @property def test_run(self): """The TestRun object. Returns: |:class:`TestRun`| """ return self._test_run @property def test_run_config(self): """The TestRunConfig for this test run. Returns: |:class:`TestRunConfig`| = This looks like a dictionary. """ return self._test_run_config @property def tools(self): """A dictionary of Tool objects. Returns: |{str::class:`Tool`}| """ return self._tools