def __init__(self, config): self.config = config self.modules_config = config._modules self.loaded_modules = {} self.loaded_methods = None self.module_log = Logger() self.start_up()
def execute_tests(self): Logger.count_time() # Initialize Engine self.run_log.separate( "Pyroute Acceptance Testing Framework (insert logo)") session = Pyroute.EngineInitializer(self.config) # Start testing session.start()
class ModuleEngine(object): """ This class implements the Module loading specifics. """ def __init__(self, config): self.config = config self.modules_config = config._modules self.loaded_modules = {} self.loaded_methods = None self.module_log = Logger() self.start_up() def start_up(self): loaded = self.module_log.process("Loading modules", self.load_modules) self.loaded_methods = self.load_methods() self.module_log.custom("[{:0>3}]".format(loaded), "Modules loaded") def get_module_classes(self, loaded, name): # Get valid Module classes, a valid module class ends with "Module" mod_dict = vars(loaded) name = name.upper() mod_ = ((k, v) for k, v in mod_dict.items() if name in k.upper() and "MODULE" in k.upper()) return tuple(mod_)[0] def load_modules(self): config = self.config._modules path = os.path.dirname(os.path.realpath(__file__)) + "/modules/" dir_contents = Utils.clean_filenames(os.listdir(path)) modules = set(self.config._modules).intersection(dir_contents) for module in modules: dir_path = path + module + ".py" loaded_mod_ = PyrouteImporter.load(module, dir_path) mod_ = self.get_module_classes(loaded_mod_, module) instance_ = mod_[1](config[module]) self.loaded_modules[mod_[0].upper()] = instance_ loaded = len(self.loaded_modules.keys()) return loaded def load_methods(self): """ This method loads all methods from the modules, and filters out the common ones (between modules) """ modules = self.loaded_modules methods = Utils.get_methods(modules) ambiguous_attrs = Utils.get_shared_attrs(modules) for attr in ambiguous_attrs: methods.pop(attr, None) return (modules, methods, ambiguous_attrs)
class ITester(object): def __init__(self, modules, methods, ambiguity_set): self.__config = Configuration("config/config.json") self.__loaded_modules = modules self.__loaded_methods = methods self.__ambiguity_set = ambiguity_set self.__log = Logger() def say(self, message): """ This method sends a custom message to the Logger. Use this for debugging. `- message`: The text to be displayed. """ self.__log.custom("[-I-]", str(message)) def sleep(self): pass def __getitem__(self, modname): # Allow 'I' to be used like a dictionary to specify # a Module in ambiguous scenarios return self.__loaded_modules[(modname.upper() + "MODULE")] def __setattr__(self, attr, value): # Write-protect 'I' (bar the initial parameters) if attr in ("_ITester__config", "_ITester__loaded_modules", "_ITester__loaded_methods", "_ITester__ambiguity_set", "_ITester__log"): object.__setattr__(self, attr, value) else: # The logger will take care of this in the future err = "Cannot assign to '{0}'. Only use a module methods to interface with it.".format( attr) raise AssignmentError(err) def __getattr__(self, attr): """ First load the method if it is available in any module. If two or more modules share the same method, raises an error. """ if attr in self.__loaded_methods: return getattr(self.__loaded_methods[attr], attr) if attr in self.__ambiguity_set: err = "Two or more modules share the same method. Use the dictionary syntax to specify a module. Ex: I[module_name].{0}".format( attr) raise AmbiguousMethodCallError(err) else: err = "No module has a method or property called '{0}'".format( attr) raise MethodNotFoundError(err)
class Run(object): def __init__(self, config=None): self.config = Configuration(config) self.module_list = [] self.run_log = Logger() def execute_tests(self): Logger.count_time() # Initialize Engine self.run_log.separate( "Pyroute Acceptance Testing Framework (insert logo)") session = Pyroute.EngineInitializer(self.config) # Start testing session.start()
def __init__(self, modules, methods, ambiguity_set): self.__config = Configuration("config/config.json") self.__loaded_modules = modules self.__loaded_methods = methods self.__ambiguity_set = ambiguity_set self.__log = Logger()
def __init__(self, config, module_engine): self.config = config self.module_engine = module_engine self.loaded_methods = self.module_engine.loaded_methods self.I = ITester(*self.loaded_methods) self.engine_log = Logger()
class PyrouteTestEngine(object): """ Pyroute's default engine "PYT", runs every test listed in config. Check the documentation for more details about the test format. """ def __init__(self, config, module_engine): self.config = config self.module_engine = module_engine self.loaded_methods = self.module_engine.loaded_methods self.I = ITester(*self.loaded_methods) self.engine_log = Logger() def get_tests(self): """ Test finder allows the user to specify tests with and without a '.py' and also allows the user to specify a directory path with and without "/" if there's a file and a folder with the same name, the file and the folder and its files will be loaded. """ tests_path = [] for test in self.config._tests['path']: test_path = '{}/{}'.format(os.getcwd(),test) py_file = '{}.py'.format(test_path) if os.path.isdir(test_path): folder = os.listdir(test_path) files =[os.path.join(test_path, file) for\ file in folder if file.endswith(".py")] [tests_path.append(file) for file in files] if os.path.isfile(py_file): tests_path.append(py_file) else: tests_path.append(test_path) return tests_path def load_tests(self): """ Loads tests. Self explanatory. This method uses PyrouteImporter, the same mechanism behind the module system, to load them. More details in 'utils.py' """ paths = self.get_tests() loaded_tests = {} for testpath in paths: testfile = os.path.basename(testpath) testname = str(testfile)[:-3] # Name without the '.py' extension loaded = PyrouteImporter.load(testfile, testpath) loaded_tests[testname] = loaded return loaded_tests def get_test_cases(self, test): """ Comprehension to filter the test cases we are interested in. Before this, the test object has some properties we don't case about, thus we filter them out. We also filter out those tests that don't start with the preffix specified in the configuration file. """ cases = (case_name for case_name in dir(test) if not case_name.startswith("__") and case_name.startswith(self.config._tests['preffix'])) return cases def run_cases(self, test_name, test, cases): """ Runs cases, self explanatory. The process method is explained in the Logger, but basically it acts as a wrapper. """ for case in cases: message = "Running test: {0} - Case: {1}".format(test_name, case) self.engine_log.process(message, getattr(test, case), self.I) def _start_engine(self): """ This function is called by the EngineInitializer. For now, it counts the passed tests, and runs each case, per test. The Logger here does nothing, it is intended to run the background tracer to deal with errors. """ passed = 0 loaded_tests = self.engine_log.process("Loading tests", self.load_tests) loaded = len(loaded_tests.keys()) self.engine_log.custom("[{:0>3}]".format(loaded), "Tests loaded") for name, test in loaded_tests.items(): cases = self.get_test_cases(test) self.run_cases(name, test, cases) message_end = "Test: {0} --- Finished".format(name) self.engine_log.custom("[-O-]", message_end) passed += 1 self.finish(passed) # This function runs at the end of all tests, anything done at that time goes here def finish(self, passed_tests): self.engine_log.custom("[>:D]", "All tests completed") self.engine_log.separate("<<<< {0} Passed in {1:.3}s >>>>".format(passed_tests, Logger.elapsed_time()))
def finish(self, passed_tests): self.engine_log.custom("[>:D]", "All tests completed") self.engine_log.separate("<<<< {0} Passed in {1:.3}s >>>>".format(passed_tests, Logger.elapsed_time()))
def __init__(self, config=None): self.config = Configuration(config) self.module_list = [] self.run_log = Logger()