def test_register_all_tc_types(self): # Set up mocks plugin_class = mock.MagicMock() plugin_class.init = mock.MagicMock() plugin_class.get_bench_api = mock.MagicMock() plugin_class.get_parsers = mock.MagicMock() plugin_class.get_external_services = mock.MagicMock() mock_bench = mock.MagicMock(spec=[]) mock_bench.logger = mock.MagicMock(return_value=mock.MagicMock()) mock_bench_function = mock.MagicMock() mock_parser = mock.MagicMock() plugin_class.get_bench_api.return_value = { "mock_func": mock_bench_function } plugin_class.get_external_services.return_value = { "mock_class": mock.MagicMock } plugin_class.get_parsers.return_value = {"mock_parser": mock_parser} mock_parsermanager = mock.MagicMock() mock_parsermanager.add_parser = mock.MagicMock() mock_parsermanager.has_parser = mock.MagicMock(return_value=False) pm = PluginManager(bench=mock_bench, responseparser=mock_parsermanager) pm.register_tc_plugins("test_plugin", plugin_class) # Asserts self.assertEqual(len(pm.registered_plugins), 1) self.assertEqual(pm.registered_plugins[0], "test_plugin") self.assertEqual(len(pm._external_services), 1) mock_parsermanager.has_parser.assert_called_once_with("mock_parser") mock_parsermanager.add_parser.assert_called_once_with( "mock_parser", mock_parser)
def _init_pluginmanager(self): """ Initialize PluginManager and load run wide plugins. """ self.pluginmanager = PluginManager(logger=self.logger) self.logger.debug("Registering execution wide plugins:") self.pluginmanager.load_default_run_plugins() self.pluginmanager.load_custom_run_plugins(self.args.plugin_path) self.logger.debug("Execution wide plugins loaded and registered.")
def test_load_custom_plugin_exception(self, mock_importer): mock_bench = mock.MagicMock(spec=[]) mock_parsermanager = mock.MagicMock() mock_importer.import_module = mock.MagicMock(side_effect=[ImportError]) pm = PluginManager(bench=mock_bench, responseparser=mock_parsermanager) with self.assertRaises(PluginException): pm.load_custom_tc_plugins( os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_plugin/load_test_plugins.py"))
def test_load_custom_plugins(self): modules = sys.modules mock_bench = mock.MagicMock(spec=[]) mock_parsermanager = mock.MagicMock() pm = PluginManager(bench=mock_bench, responseparser=mock_parsermanager) pm.register_tc_plugins = mock.MagicMock() pm.load_custom_tc_plugins( os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_plugin/load_test_plugins.py")) sys.modules = modules pm.register_tc_plugins.assert_called_once()
def init(self, benchapi, logger=None): """ Initialize Parser and Plugin managers. :return: Nothing """ self._env = benchapi.env if logger: self._logger = logger self._parser_manager = ParserManager(self._logger) self._pluginmanager = PluginManager(responseparser=self._parser_manager, bench=benchapi, logger=self._logger)
def test_register_and_start_service(self): # Set up mocks plugin_class = mock.MagicMock() plugin_class.init = mock.MagicMock() plugin_class.get_bench_api = mock.MagicMock() plugin_class.get_parsers = mock.MagicMock() plugin_class.get_external_services = mock.MagicMock() mock_bench = mock.MagicMock(spec=[]) mock_bench.logger = mock.MagicMock(return_value=mock.MagicMock()) plugin_class.get_bench_api.return_value = None mock_class = mock.MagicMock() plugin_class.get_external_services.return_value = { "mock_class": mock_class } plugin_class.get_parsers.return_value = None mock_parsermanager = mock.MagicMock() pm = PluginManager(bench=mock_bench, responseparser=mock_parsermanager) pm.register_tc_plugins("test_plugin", plugin_class) pm.start_external_service("mock_class") self.assertEqual(len(pm._started_services), 1) pm.stop_external_services() self.assertEqual(len(pm._started_services), 0) self.assertEqual(len(pm._external_services), 1) mock_class.assert_called_once()
def test_register_start_stop_service(self): # pylint: disable=invalid-name plugin_class = mock.MagicMock() plugin_class.init = mock.MagicMock() plugin_class.get_bench_api = mock.MagicMock() plugin_class.get_parsers = mock.MagicMock() plugin_class.get_external_services = mock.MagicMock() mock_bench = mock.MagicMock(spec=[]) mock_bench.logger = mock.MagicMock(return_value=mock.MagicMock()) plugin_class.get_bench_api.return_value = None mocked_service = mock.MagicMock() mocked_service.start = mock.MagicMock() mocked_service.stop = mock.MagicMock(side_effect=[PluginException]) mock_class = mock.MagicMock(return_value=mocked_service) plugin_class.get_external_services.return_value = { "mock_class": mock_class } plugin_class.get_parsers.return_value = None mock_parsermanager = mock.MagicMock() pluginmanager = PluginManager(bench=mock_bench, responseparser=mock_parsermanager) pluginmanager.register_tc_plugins("test_plugin", plugin_class) pluginmanager.start_external_service("mock_class") self.assertEqual(len(pluginmanager._started_services), 1) pluginmanager.stop_external_services() self.assertEqual(len(pluginmanager._started_services), 0) self.assertEqual(len(pluginmanager._external_services), 1) mock_class.assert_called_once()
def test_register_raises_pluginexception(self): plugin_class = mock.MagicMock() plugin_class.init = mock.MagicMock() plugin_class.get_bench_api = mock.MagicMock() mock_bench = mock.MagicMock(spec=[]) mock_bench.logger = mock.MagicMock(return_value=mock.MagicMock()) mock_bench_function = mock.MagicMock() mock_parser = mock.MagicMock() plugin_class.get_bench_api.return_value = { "mock_func": mock_bench_function } mock_parsermanager = mock.MagicMock() mock_parsermanager.add_parser = mock.MagicMock() mock_parsermanager.has_parser = mock.MagicMock(return_value=False) pm = PluginManager(bench=mock_bench, responseparser=mock_parsermanager) pm.registered_plugins = ["test_plugin"] with self.assertRaises(PluginException): pm.register_tc_plugins("test_plugin", plugin_class)
def test_start_service_raises_exception(self): # Set up mocks plugin_class = mock.MagicMock() plugin_class.init = mock.MagicMock() plugin_class.get_bench_api = mock.MagicMock() plugin_class.get_parsers = mock.MagicMock() plugin_class.get_external_services = mock.MagicMock() mock_bench = mock.MagicMock(spec=[]) mock_bench.logger = mock.MagicMock(return_value=mock.MagicMock()) plugin_class.get_bench_api.return_value = None mocked_service = mock.MagicMock() mock_class = mock.MagicMock(return_value=mocked_service) mocked_service.start = mock.MagicMock() mocked_service.start.side_effect = [PluginException] plugin_class.get_external_services.return_value = { "mock_class": mock_class } plugin_class.get_parsers.return_value = None mock_parsermanager = mock.MagicMock() pm = PluginManager(bench=mock_bench, responseparser=mock_parsermanager) pm.register_tc_plugins("test_plugin", plugin_class) with self.assertRaises(PluginException): pm.start_external_service("mock_class") mocked_service.start.assert_called_once()
def test_load_defaults(self): bench = mock.MagicMock(spec=[]) bench.logger = mock.MagicMock(return_value=mock.MagicMock()) rp = mock.MagicMock() rp.append = mock.MagicMock() rp.has_parser = mock.MagicMock(return_value=False) pm = PluginManager(bench=bench, responseparser=rp) pm.load_default_tc_plugins() pm.load_default_run_plugins() length = len(default_plugins) self.assertEqual(len(pm.registered_plugins), length)
class Plugins(object): """ This Mixer manage Test used Plugins. """ def __init__(self, logger, env, args, config): super(Plugins, self).__init__() self._parser_manager = None self._pluginmanager = None self._logger = logger self._env = env self._args = args self._config = config def init(self, benchapi, logger=None): """ Initialize Parser and Plugin managers. :return: Nothing """ self._env = benchapi.env if logger: self._logger = logger self._parser_manager = ParserManager(self._logger) self._pluginmanager = PluginManager(responseparser=self._parser_manager, bench=benchapi, logger=self._logger) def load_plugins(self): """ Initialize PluginManager and Load bench related plugins. :return: Nothing """ self._pluginmanager.load_default_tc_plugins() self._pluginmanager.load_custom_tc_plugins(self._args.plugin_path) @property def pluginmanager(self): """ Getter for PluginManager. :return: PluginManager """ return self._pluginmanager @pluginmanager.setter def pluginmanager(self, value): """ Setter for PluginManager. """ self._pluginmanager = value # All required external services starting here def start_external_services(self): """ Start ExtApps required by test case. :return: Nothing """ apps = get(self._config, 'requirements.external.apps', []) for app in apps: # Check if we have an environment configuration for this app conf = app try: conf = merge(conf, self._env["extApps"][app["name"]]) except KeyError: self._logger.warning("Unable to merge configuration for app %s", app, exc_info=True if not self._args.silent else False) if 'name' in app: try: self.pluginmanager.start_external_service(app['name'], conf=conf) except PluginException: self._logger.error("Failed to start requested external services.") raise EnvironmentError("Failed to start requested external services.") self._logger.info("done") else: conf_path = None conf_cmd = None try: conf_path = conf["path"] except KeyError: self._logger.warning("No path defined for app %s", app) try: conf_cmd = conf["cmd"] except KeyError: self._logger.warning("No command defined for app %s", app) appname = 'generic' newapp = GenericProcess(name=appname, path=conf_path, cmd=conf_cmd) newapp.ignore_return_code = True newapp.start_process() def stop_external_services(self): """ Stop external services started via PluginManager """ self._logger.debug("Stop external services if any") self.pluginmanager.stop_external_services() def parse_response(self, cmd, response): """ Parse a response for command cmd. :param cmd: Command :param response: Response :return: Parsed response (usually dict) """ return self._parser_manager.parse(cmd, response)
class IceteaManager(object): """ IceteaManager class. This is the master of the entire run. The primary entry point into execution is the run method. """ def __init__(self): """ Constructor for IceteaManager. Appends libraries to sys.path, loads the test case metadata schema, parses arguments and initializes logging. """ self.libpath = os.sep.join( os.path.abspath(__file__).split(os.sep)[:-1]) sys.path.append(self.libpath) libpath2 = os.sep.join(self.libpath.split(os.sep)[:-1]) sys.path.append(libpath2) # Initialize TCMetaSchema with correct libpath TCMetaSchema(self.libpath) self.args, self.unknown = IceteaManager._parse_arguments() # If called with --clean, clean up logs. if self.args.clean: _cleanlogs(silent=self.args.silent, log_location=self.args.log) LogManager.init_base_logging( self.args.log, verbose=self.args.verbose, silent=self.args.silent, color=self.args.color, no_file=(self.args.list or self.args.listsuites), truncate=not self.args.disable_log_truncate) self.logger = LogManager.get_logger("icetea") self.pluginmanager = None self.resourceprovider = ResourceProvider(self.args) self._init_pluginmanager() self.resourceprovider.set_pluginmanager(self.pluginmanager) @staticmethod def list_suites(suitedir="./testcases/suites", cloud=False): """ Static method for listing suites from both local source and cloud. Uses PrettyTable to generate the table. :param suitedir: Local directory for suites. :param cloud: cloud module :return: PrettyTable object or None if no test cases were found """ suites = [] suites.extend(TestSuite.get_suite_files(suitedir)) # no suitedir, or no suites -> append cloud.get_campaigns() if cloud: names = cloud.get_campaign_names() if names: suites.append("------------------------------------") suites.append("FROM CLOUD:") suites.extend(names) if not suites: return None from prettytable import PrettyTable table = PrettyTable(["Testcase suites"]) for suite in suites: table.add_row([suite]) return table @staticmethod def _parse_arguments(): """ Static method for paring arguments """ parser = get_base_arguments(get_parser()) parser = get_tc_arguments(parser) args, unknown = parser.parse_known_args() return args, unknown def check_args(self): """ Validates that a valid number of arguments were received and that all arguments were recognised. :return: True or False. """ parser = get_base_arguments(get_parser()) parser = get_tc_arguments(parser) # Disable "Do not use len(SEQ) as condition value" # pylint: disable=C1801 if len(sys.argv) < 2: self.logger.error("Icetea called with no arguments! ") parser.print_help() return False elif not self.args.ignore_invalid_params and self.unknown: self.logger.error( "Unknown parameters received, exiting. " "To ignore this add --ignore_invalid_params flag.") self.logger.error("Following parameters were unknown: {}".format( self.unknown)) parser.print_help() return False return True def _init_pluginmanager(self): """ Initialize PluginManager and load run wide plugins. """ self.pluginmanager = PluginManager(logger=self.logger) self.logger.debug("Registering execution wide plugins:") self.pluginmanager.load_default_run_plugins() self.pluginmanager.load_custom_run_plugins(self.args.plugin_path) self.logger.debug("Execution wide plugins loaded and registered.") def run(self, args=None): """ Runs the set of tests within the given path. """ # Disable "Too many branches" and "Too many return statemets" warnings # pylint: disable=R0912,R0911 retcodesummary = ExitCodes.EXIT_SUCCESS self.args = args if args else self.args if not self.check_args(): return retcodesummary if self.args.clean: if not self.args.tc and not self.args.suite: return retcodesummary # If called with --version print version and exit version = get_fw_version() if self.args.version and version: print(version) return retcodesummary elif self.args.version and not version: print( "Unable to get version. Have you installed Icetea correctly?") return retcodesummary self.logger.info( "Using Icetea version {}".format(version) if version else "Unable to get Icetea version. Is Icetea installed?") # If cloud set, import cloud, get parameters from environment, initialize cloud cloud = self._init_cloud(self.args.cloud) # Check if called with listsuites. If so, print out suites either from cloud or from local if self.args.listsuites: table = self.list_suites(self.args.suitedir, cloud) if table is None: self.logger.error("No suites found!") retcodesummary = ExitCodes.EXIT_FAIL else: print(table) return retcodesummary try: testsuite = TestSuite(logger=self.logger, cloud_module=cloud, args=self.args) except SuiteException as error: self.logger.error( "Something went wrong in suite creation! {}".format(error)) retcodesummary = ExitCodes.EXIT_INCONC return retcodesummary if self.args.list: if self.args.cloud: testsuite.update_testcases() testcases = testsuite.list_testcases() print(testcases) return retcodesummary results = self.runtestsuite(testsuite=testsuite) if not results: retcodesummary = ExitCodes.EXIT_SUCCESS elif results.failure_count( ) and self.args.failure_return_value is True: retcodesummary = ExitCodes.EXIT_FAIL elif results.inconclusive_count( ) and self.args.failure_return_value is True: retcodesummary = ExitCodes.EXIT_INCONC return retcodesummary def runtestsuite(self, testsuite): """ Runs a single test suite :param testsuite: TestSuite :return: ResultList """ if testsuite.status == TestStatus.READY: results = testsuite.run() else: results = ResultList() # Disable "Expression is assigned to nothing" warning # pylint: disable=W0106 [handler.flush() for handler in self.logger.handlers] results.save(heads={'Build': '', 'Branch': self.args.branch}) sys.stdout.flush() self._cleanup_resourceprovider() return results # Disable "String statement has no effect" warning # pylint: disable=W0105 """ PRIVATE FUNCTIONS HERE """ def _cleanup_resourceprovider(self): """ Calls cleanup for ResourceProvider of this run. :return: Nothing """ # Disable too broad exception warning # pylint: disable=W0703 self.resourceprovider = ResourceProvider(self.args) try: self.resourceprovider.cleanup() self.logger.info("Cleanup done.") except Exception as error: self.logger.error("Cleanup failed! %s", error) def _init_cloud(self, cloud_arg): """ Initializes Cloud module if cloud_arg is set. :param cloud_arg: taken from args.cloud :return: cloud module object instance """ # Disable too broad exception warning # pylint: disable=W0703 cloud = None if cloud_arg: try: if hasattr(self.args, "cm"): cloud_module = self.args.cm if self.args.cm else None self.logger.info( "Creating cloud module {}.".format(cloud_module)) else: cloud_module = None cloud = Cloud(host=None, module=cloud_module, logger=self.logger, args=self.args) except Exception as error: self.logger.warning( "Cloud module could not be initialized: {}".format(error)) cloud = None return cloud