def run(self, argv): """Run the test runner. Invoke the test runner by calling it. """ cf = self.runner.config cf.flags.INTERACTIVE = True cf.flags.DEBUG = 0 cf.flags.VERBOSE = 0 optlist, longopts, args = getopt.getopt(argv[1:], "h?dDvIc:f:m:e:r:") for opt, optarg in optlist: if opt in ("-h", "-?"): print(TestRunnerInterfaceDoc.format( name=os.path.basename(argv[0]))) return elif opt == "-d": cf.flags.DEBUG += 1 elif opt == "-D": from pycopia import autodebug # noqa elif opt == "-v": cf.flags.VERBOSE += 1 elif opt == "-I": cf.flags.INTERACTIVE = False elif opt == "-c" or opt == "-f": cf.mergefile(optarg) elif opt == "-m": cf.comment = optarg elif opt == "-r": cf.reportname = optarg elif opt == "-e": cf.environmentname = optarg cf.evalupdate(longopts) # original command line arguments saved for the report cf.arguments = [os.path.basename(argv[0])] + argv[1:] ui = UI.get_userinterface(themename="ANSITheme") if not args: from . import simplechooser args = simplechooser.choose_tests(ui) if not args: return 10 objects, errors = module.get_objects(args) if errors: logging.warn("Errors found while loading test object:") for error in errors: logging.warn(error) if objects: cf.argv = args rv = self.runner.run(objects, ui) if rv is None: return 11 else: try: return int(rv) except TypeError: return 12 else: return len(errors) + 20
def __call__(self, argv): """Run the test runner. Invoke the test runner by calling it. """ cf = self.runner.config cf.flags.REPORT = False cf.flags.INTERACTIVE = False cf.flags.DEBUG = 0 cf.flags.VERBOSE = 0 optlist, extraopts, args = getopt.getopt(argv[1:], "h?dDviIrc:f:n:") for opt, optarg in optlist: if opt in ("-h", "-?"): print (TestRunnerInterfaceDoc % (os.path.basename(argv[0]),)) return elif opt == "-d": cf.flags.DEBUG += 1 elif opt == "-D": from pycopia import autodebug # top-level debug for framework bugs elif opt == "-v": cf.flags.VERBOSE += 1 elif opt == "-i": cf.flags.INTERACTIVE = True elif opt == "-I": cf.flags.INTERACTIVE = False elif opt == "-c" or opt == "-f": cf.mergefile(optarg) elif opt == "-n": cf.comment = optarg elif opt == "-r": cf.flags.REPORT = True cf.evalupdate(extraopts) # original command line arguments saved for the report cf.arguments = [os.path.basename(argv[0])] + argv[1:] # Save extra options for overriding configuration after a mergefile # because command line options should have highest precedence. self.runner.set_options(extraopts) if not args: if cf.flags.REPORT: self.runner.report_global() return 0 else: args = choose_tests() if not args: return 2 objects, errors = module.get_objects(args) if errors: logging.warn("Errors found while loading test object:") for error in errors: logging.warn(error) if objects: cf.argv = args self.runner.initialize() rv = self.runner.run_objects(objects) self.runner.finalize() return not rv # inverted due to shell semantics (zero is good) being different from result code else: return int(bool(errors)) + 2
def run_objects(self, objects): """Invoke the `run` method on a list of mixed runnable objects. Arguments: objects: A list of runnable objects. A runnable object is basically something that has a callable named "run" that takes a configuration object as a parameter. May raise TestRunnerError if an object is not runnable by this test runner. """ rv = 0 testcases = [] for obj in objects: objecttype = type(obj) if objecttype is ModuleType and hasattr(obj, "run"): rv = self.run_module(obj) elif objecttype is TypeType and issubclass(obj, core.Test): testcases.append(obj) elif isinstance(obj, core.TestSuite): rv = self.run_object(obj) elif objecttype is type and hasattr(obj, "run"): # a bare class uses as a subcontainer of test or suite constructor. rv = self.run_class(obj) else: logging.warn("%r is not a runnable object." % (obj,)) if testcases: if len(testcases) > 1: rv = self.run_tests(testcases) else: args = [] kwargs = {} opts = self.config.options_override.copy() for name, value in opts.items(): if name.startswith("arg"): try: index = int(name[3]) # use --arg1=XXX to place argument XXX except (ValueError, IndexError): logging.warn("{!r} not converted to argument.".format(name)) else: try: args[index] = value except IndexError: need = index - len(args) while need: args.append(None) need -= 1 args.append(value) del self.config.options_override[name] del self.config[name] elif name.startswith("kwarg_"): # use --kwarg_XXX to place keyword argument XXX kwargs[name[6:]] = value del self.config.options_override[name] del self.config[name] rv = self.run_test(testcases[0], *args, **kwargs) return rv
def import_module(self, modname): if _DEBUG: print("Doing module: %s" % modname) try: mod = module.get_module(modname) do_module(mod, self.config) except: ex, val, tb = sys.exc_info() if _DEBUG: debugger.post_mortem(tb, ex, val) else: logging.warn("Could not import %s: %s" % ( modname, "%s: %s" % (ex, val)))
def run_objects(self, objects): """Invoke the `run` method on a list of mixed runnable objects. Arguments: objects: A list of runnable objects. A runnable object is basically something that has a callable named "run" that takes a configuration, environment, and UI object as a parameter. A special module with an "execute" function can also be run. May raise TestRunnerError if an object is not runnable by this test runner. Bare TestCase classes are grouped together and run in a temporary TestSuite. """ rv = TestResult.INCOMPLETE results = [] testcases = [] for obj in objects: objecttype = type(obj) if objecttype is type: if issubclass(obj, core.TestCase): testcases.append(obj) if issubclass(obj, core.UseCase): rv = obj.run(self.config, self.environment, self._ui) elif isinstance(obj, core.TestSuite): obj.run() rv = obj.result elif objecttype is ModuleType: if hasattr(obj, "execute"): rv = self._run_module_hack(obj) elif hasattr(obj, "run"): rv = self._run_module(obj) else: logging.warn("{!r} is not a runnable object.".format(obj)) results.append(rv) # Run any accumulated bare test classes. if testcases: if len(testcases) > 1: rv = self.run_tests(testcases) else: rv = self.run_test(testcases[0]) results.append(rv) return _aggregate_returned_results(results)
def get_TestEntry_instance(string, config): """Return a TestEntry instance from a string representing a test class plus arguments. """ paren_i = string.find("(") if paren_i > 0: args = string[paren_i+1:-1] string = string[:paren_i] args, kwargs = core.parse_args(args) else: args = () kwargs = {} try: cls = module.get_object(string) except (module.ModuleImportError, module.ObjectImportError), err: logging.warn(err) return None
def get_test_jobs(args): dbsession = models.get_session() TJ = models.TestJob for jobid in args: try: jobid = int(jobid) except ValueError: pass try: if type(jobid) is int: testjob = dbsession.query(TJ).get(jobid) else: testjob = dbsession.query(TJ).filter(TJ.name==jobid).one() except models.NoResultFound: logging.warn("No TestJob with id %r" % jobid) continue else: yield testjob
def resolve_prerequisite(self, testinstance): doc_prereqs = self._many2many["prerequisites"] self._many2many["prerequisites"] = [] memo = set() for prereq in aid.removedups([pr.implementation for pr in testinstance.prerequisites] + doc_prereqs): if not _valid_prereq(prereq): continue if "." not in prereq: prereq = "%s.%s" % (testinstance.__class__.__module__, prereq) if prereq in memo: continue memo.add(prereq) entry = get_TestEntry_instance(prereq, testinstance.config) if entry: dbprereq = do_TestEntry(entry) self._many2many["prerequisites"].append(dbprereq) else: logging.warn("prerequisite %r could not be found." % (prereq,))
def get_test_suites(self, args): """Generator that yields valid TestSuite records from the database. """ TS = models.TestSuite for suiteid in args: try: suiteid = int(suiteid) except ValueError: pass try: if type(suiteid) is int: suite = self.dbsession.query(TS).get(suiteid) else: suite = self.dbsession.query(TS).filter(models.and_(TS.name==suiteid, TS.valid==True)).one() except models.NoResultFound: logging.warn("No TestSuite with id or name %r" % suiteid) continue else: yield suite
def choose_tests(): try: import testcases except ImportError: logging.warn("Cannot find 'testcases' base package.") return None from pycopia import UI from pycopia.QA import core ui = UI.get_userinterface(themename="ANSITheme") ui.printf("Select any number of runnable objects. %n" "You can select %wmodules%N, %gUseCase%N objects, or single %yTest%N object.") # callback for testdir walker def filternames(flist, dirname, names): for name in names: if name.endswith(".py") and not name.startswith("_"): flist.append(os.path.join(dirname, name[:-3])) modnames = [] runnables = [] for testbase in testcases.__path__: mnlist = [] os.path.walk(testbase, filternames, mnlist) testhome_index = len(os.path.dirname(testbase)) + 1 modnames.extend(map(lambda n: n[testhome_index:].replace("/", "."), mnlist)) modnames.sort() for modname in modnames: try: mod = module.get_module(modname) except module.ModuleImportError: ui.warning(" Warning: could not import '{}'".format(modname)) continue if getattr(mod, "run", None) is not None: runnables.append(FormatWrapper(ui, modname, None, "%w%U%N")) for attrname in dir(mod): obj = getattr(mod, attrname) if type(obj) is type: if issubclass(obj, core.UseCase): runnables.append(FormatWrapper(ui, modname, obj.__name__, "%U.%g%O%N")) if issubclass(obj, core.Test): runnables.append(FormatWrapper(ui, modname, obj.__name__, "%U.%y%O%N")) return [o.fullname for o in ui.choose_multiple(runnables, prompt="Select tests")]
def skippedEntity(self, name): warn("unhandled ignorableWhitespace: %r" % (whitespace,))
def run_server(argv): username = None do_daemon = True debug = False killserver = False try: optlist, args = getopt.getopt(argv[1:], "dnh?kl:f:p:s:") except getopt.GetoptError: print (run_server._doc % (argv[0],)) return if len(args) > 0: servername = args[0] else: servername = os.path.basename(argv[0]) logfilename = "/var/log/%s.log" % (servername,) cffilename = "/etc/pycopia/%s.conf" % (servername,) pidfile="/var/run/%s.pid" % (servername,) socketpath = '/tmp/%s.sock' % (servername,) for opt, optarg in optlist: if opt == "-n": do_daemon = False elif opt == "-k": killserver = True elif opt == "-d": debug = True elif opt == "-u": username = optarg elif opt == "-l": logfilename = optarg elif opt == "-f": cffilename = optarg elif opt == "-p": pidfile = optarg elif opt == "-s": socketpath = optarg elif opt in ("-h", "-?"): print (run_server._doc % (argv[0],)) return 2 try: config = basicconfig.get_config(cffilename, CONFIGFILE=cffilename, PIDFILE=pidfile, SOCKETPATH=socketpath, LOGFILENAME=logfilename, DEBUG=debug, SERVERNAME=servername) except: ex, val, tb = sys.exc_info() logging.warn("Could not get server config: %s (%s)" % (ex, val)) return 1 if username: config.USERNAME = username if killserver: kill_server(config) return 0 if check4server(config): logging.warn("Server %r already running on socket %r." % (servername, socketpath)) return 1 if do_daemon and not debug: from pycopia import daemonize from pycopia import logfile lf = logfile.ManagedStdio(logfilename) daemonize.daemonize(lf, pidfile=pidfile) else: # for controller fo = open(pidfile, "w") fo.write("%s\n" % (os.getpid(),)) fo.close() del fo server = get_server(config) return int(server.run())
def run_server(argv): username = None do_daemon = True debug = False killserver = False try: optlist, longopts, args = getopt.getopt(argv[1:], "dnh?kl:f:p:s:") except getopt.GetoptError: print(run_server._doc.format(procname=argv[0])) return if len(args) > 0: servername = args[0] else: servername = os.path.basename(argv[0]) logfilename = "/var/log/{}.log".format(servername) cffilename = "/etc/pycopia/{}.conf".format(servername) pidfile = "/var/run/{}.pid".format(servername) socketpath = '/tmp/{}.sock'.format(servername) for opt, optarg in optlist: if opt == "-n": do_daemon = False elif opt == "-k": killserver = True elif opt == "-d": from pycopia import autodebug # noqa debug = True elif opt == "-u": username = optarg elif opt == "-l": logfilename = optarg elif opt == "-f": cffilename = optarg elif opt == "-p": pidfile = optarg elif opt == "-s": socketpath = optarg elif opt in ("-h", "-?"): print(run_server._doc.format(procname=argv[0])) return 2 try: config = basicconfig.get_config(cffilename, CONFIGFILE=cffilename, PIDFILE=pidfile, SOCKETPATH=socketpath, LOGFILENAME=logfilename, DEBUG=debug, SERVERNAME=servername) except: ex, val, tb = sys.exc_info() logging.warn( "Could not get server config: {} ({})".format(ex.__name__, val)) return 1 config.update(longopts) if username: config.USERNAME = username if killserver: kill_server(config) return 0 if check4server(config): logging.warn( "Server {!r} already running on socket {!r}.".format(servername, socketpath)) return 1 if do_daemon and not debug: from pycopia import daemonize from pycopia import logfile lf = logfile.ManagedStdio(logfilename) daemonize.daemonize(lf, pidfile=pidfile) else: # for controller with open(pidfile, "w") as fo: fo.write("{}\n".format(os.getpid())) server = get_server(config) return int(server.run())
def warning(self, exception): "Handle a warning." warn("XML Warning: %s" % (exception,))
def fatalError(self, exception): "Handle a non-recoverable error." #raise exception warn("XML fatalError: %s" % (exception,))
def error(self, exception): "Handle a recoverable error." #raise exception warn("XML error: %s" % (exception,))
def unparsedEntityDecl(self, name, publicId, systemId, ndata): warn("unhandled unparsedEntityDecl: %r %r %r %r" % ( name, publicId, systemId, ndata))
def notationDecl(self, name, publicId, systemId): """Handle a notation declaration event.""" warn("unhandled notationDecl: %r %r %r" % ( name, publicId, systemId))
def startPrefixMapping(self, prefix, uri): warn("!!! Unhandled prefix: %r" % (prefix,))
def startPrefixMapping(self, prefix, uri): warn("!!! Unhandled prefix: %r" % (prefix, ))
def skippedEntity(self, name): warn("unhandled ignorableWhitespace: %r" % (whitespace, ))
def ignorableWhitespace(self, whitespace): warn("unhandled ignorableWhitespace: %r" % (whitespace,))
def run_server(argv): username = None do_daemon = True debug = False killserver = False try: optlist, longopts, args = getopt.getopt(argv[1:], "dnh?kl:f:p:s:") except getopt.GetoptError: print(run_server._doc.format(procname=argv[0])) return if len(args) > 0: servername = args[0] else: servername = os.path.basename(argv[0]) logfilename = "/var/log/{}.log".format(servername) cffilename = "/etc/pycopia/{}.conf".format(servername) pidfile = "/var/run/{}.pid".format(servername) socketpath = '/tmp/{}.sock'.format(servername) for opt, optarg in optlist: if opt == "-n": do_daemon = False elif opt == "-k": killserver = True elif opt == "-d": from pycopia import autodebug # noqa debug = True elif opt == "-u": username = optarg elif opt == "-l": logfilename = optarg elif opt == "-f": cffilename = optarg elif opt == "-p": pidfile = optarg elif opt == "-s": socketpath = optarg elif opt in ("-h", "-?"): print(run_server._doc.format(procname=argv[0])) return 2 try: config = basicconfig.get_config(cffilename, CONFIGFILE=cffilename, PIDFILE=pidfile, SOCKETPATH=socketpath, LOGFILENAME=logfilename, DEBUG=debug, SERVERNAME=servername) except: ex, val, tb = sys.exc_info() logging.warn("Could not get server config: {} ({})".format( ex.__name__, val)) return 1 config.update(longopts) if username: config.USERNAME = username if killserver: kill_server(config) return 0 if check4server(config): logging.warn("Server {!r} already running on socket {!r}.".format( servername, socketpath)) return 1 if do_daemon and not debug: from pycopia import daemonize from pycopia import logfile lf = logfile.ManagedStdio(logfilename) daemonize.daemonize(lf, pidfile=pidfile) else: # for controller with open(pidfile, "w") as fo: fo.write("{}\n".format(os.getpid())) server = get_server(config) return int(server.run())