def run_test_function(rpt, mod, name, ob): currently_running_test_name.append(name) # print "PUSHED",name if debug: debug_fd.write("run_test_function: %s\n" % (name)) # blank out the tda/tra dictionaries for each test. # poke directly into the module to do it. mod.tda = {} mod.tra = {} # start gathering up the stdout/stderr for this test pycode.snarf_stdout() # run the test start_time = time.time() # disable = getattr(ob, '__disable__', False) if not disable: try: setup = getattr(ob, 'setup', None) if setup is not None: setup() ob() status = 'P' except AssertionError: status = 'F' traceback.print_exc() except: status = 'E' traceback.print_exc() teardown = getattr(ob, 'teardown', None) if teardown is not None: try: teardown() except: print "Exception in teardown()" status = 'E' traceback.print_exc() else: # is disabled status = 'D' end_time = time.time() # collect the gathered stdout/stderr log = pycode.end_snarf_stdout() # write a report the the pandokia log file gen_report(rpt, name, status, start_time, end_time, mod.tda, mod.tra, log)
def startTest(self, test): # initialize all the reportable values about the test. We can then # assume everywhere that they exist. self.pdk_test_name = test.__class__.__name__ + '.' + test._testMethodName self.pdk_status = 'E' self.pdk_start_time = time.time() self.pdk_end_time = None # tda and tra dictionaries must be initialized to empty arrays, # but preserve any values that may have been stashed there by # the test object initialization. Note that in unittest2, every # test gets a fresh object, so we do not need to worry about # old values hanging around. test.tra = getattr(test, 'tra', {}) test.tda = getattr(test, 'tda', {}) # gather stdout for the whole test run. This includes # setUp() and tearDown(). pycode.snarf_stdout()
def main(args): # We want to gather everything that happens into the test report. # Individual tests will suck up their own stdout, so it will # not end up in the output that belongs to the file. pycode.snarf_stdout() # status is pass unless something else happens file_status = 'P' # No arg processing because pandokia left everything we need # in the environment. filename = os.environ['PDK_FILE'] # The module name is the basename of the file, without the extension. module_name = os.path.basename(filename) module_name = os.path.splitext(module_name)[0] file_start_time = time.time() if no_unittest2: print("%s Cannot import unittest2" % __file__) print(e) for x in sys.path: print(" %s" % x) file_status = 'E' else: # unittest2 is in very early stages of development. Cry if we # don't see the version we expect, because there may be incompatible # changes in the future. if unittest2.__version__ not in unittest2_versions: print( 'THIS IS NOT THE VERSION OF unittest2 THAT THE PANDOKIA RUNNER WAS WRITTEN FOR') print('HAVE %s' % unittest2.__version__) print('EXPECT ONE OF %s' % unittest2_versions) file_status = 'E' # to draw attention try: module = imp.load_source(module_name, filename) # This is a trick to pass a value to the initializer # pdk_test_result. It would be hard to go through channels # because unittest2 does not have a concept for this particular # data. I happen to know that it only makes a single TestRunner # object, so this is ok to do. pdk_runner.fixed_filename = module_name TestProgram( # module must be a loaded module to run tests from module=module, # argv must be a list with at least one element because # the TestProgram arg processing will try to read through # it whether we need it to or not. argv=['nop'], # provide it with our test runner, so it writes pandokia # logs instead of the default stuff to stdout testRunner=pdk_runner, # prevent it trying to exit when it is done exit=False, ) # Yes, the whole file can fail or error. This happens either # on import or when instantiating TestCase objects. except AssertionError: file_status = 'F' traceback.print_exc() except: file_status = 'E' traceback.print_exc() file_end_time = time.time() log = pycode.end_snarf_stdout() # We do not create the pandokia log entry object until after # everything is done. Down inside unittest2, our code is going # to open the same log file. It will close it before returning, # so we can open it here without conflicting. rpt = pycode.reporter(filename) # the name for the report on the file as a whole is derived from # the file name. the report object is already set up to do this, # so we do not need to provide any more parts of the test name. rpt.report(None, file_status, file_start_time, file_end_time, {}, {}, log) rpt.close()
def process_file(filename, test_name=None, test_args=None): global currently_running_file_name currently_running_file_name = filename if debug: debug_fd.write("begin process_file\n") debug_fd.write("file: %s\n" % filename) debug_fd.write("args: %s\n" % test_args) global dots_mode dots_mode = default_dots_mode if dots_mode: dots_file.write('File: %s\n' % filename) dots_file.flush() # the module name is the basename of the file, without the extension module_name = os.path.basename(filename) module_name = os.path.splitext(module_name)[0] # pandokia log entry object - writes the pandokia reports if debug: debug_fd.write("test_args %s\n" % test_args) # we have no name for the top level of the file - bummer currently_running_test_name.append(None) # print "PUSHED",None if test_name is not None: # if we have an explicit test name, then we are run outside # pdkrun. We need to set the defaults. rpt = pycode.reporter(test_name, setdefault=True) else: rpt = pycode.reporter(filename) # the pycode context managers can make use of this. pycode.cached_rpt = rpt # gather up the stdout from processing the whole file. individual # tests will suck up their own stdout, so it will not end up in # this log. pycode.snarf_stdout() # file_start_time = time.time() file_status = 'P' # make sure we can import from the directory where the file is sys_path_save = copy.copy(sys.path) sys.path.insert(0, os.path.dirname(filename)) exception_str = None try: if debug: debug_fd.write("process_file: about to import %s %s\n" % (module_name, filename)) # import the module module = imp.load_source(module_name, filename) if debug: debug_fd.write("process_file: import succeeds\n") if test_args: if debug: debug_fd.write("entering minipyt_external_args into module\n") module.minipyt_external_args = test_args try: dots_mode = module.minipyt_dots_mode except: pass # these are both flags and the function objects for module # setup/teardown and pycode function setup = None try: setup = module.setUp except AttributeError: pass if setup is not None: if debug: debug_fd.write("process_file: running setUp") print "setUp" setup() # look through the module for things that might be tests if debug: debug_fd.write("process_file: inspect module namespace\n") l = [] for name, ob in inspect.getmembers( module, inspect.isfunction) + inspect.getmembers( module, inspect.isclass): if debug: debug_fd.write("process_file: inspect name %s\n" % name) try: # if it has minipyt_test, that value is a flag # about whether it is a test or not. n = getattr(ob, '__test__') if n: rname = getattr(ob, '__test_name__', name) l.append((rname, ob)) continue except AttributeError: # if it does not have __test__, we consider # other criteria that may make it count as a test. pass # if the name looks like a test, it is a test if name.startswith('test') or name.endswith('test'): l.append((name, ob)) # now we have a list of all the tests in the file # we have an opportunity to get them in the order they were # defined in the file, instead of alpha. Just need to # figure out how. try: test_order = module.minipyt_test_order except: test_order = 'line' sort_test_list(l, test_order) for x in l: name, ob = x # default name is the object name # but use nose-compatible name, if present rname = getattr(ob, 'compat_func_name', name) # but use our explicitly defined name, if present rname = getattr(ob, '__test_name__', rname) # call the appropriate runner if type(ob) == function: print 'function', name, 'as', rname run_test_function(rpt, module, rname, ob) else: print 'class', name, 'as', rname run_test_class(rpt, module, name, ob, test_order) # look for a pycode function - call it if necessary # # pycode functions are obsolete, but we're keeping this until # we get rid of a few more tests that still use it. pycode_fn = None try: pycode_fn = module.pycode except AttributeError: pass if callable(pycode_fn): print 'old-style pycode test detected' pycode_fn(1, rpt=rpt) print 'tests completed' # look for a teardown function - call it if necessary teardown = None try: teardown = module.tearDown except AttributeError: pass if teardown: print "tearDown" teardown() except AssertionError: file_status = 'F' traceback.print_exc() except: file_status = 'E' traceback.print_exc() # restore sys.path sys.path = sys_path_save log = pycode.end_snarf_stdout() file_end_time = time.time() tda = {} tra = {} try: tda = module.module_tda except: pass try: tra = module.module_tra except: pass if exception_str is not None: tra['exception'] = exception_str # the name for the report on the file as a whole is derived from # the file name. the report object is already set up to do this, # so we do not need to provide any more parts of the test name. gen_report(rpt, None, file_status, file_start_time, file_end_time, tda, tra, log) rpt.close() # now that we have closed it, we can't allow anyone else to use it. pycode.cached_rpt = None if dots_mode != 'N': dots_file.write('\n') dots_file.flush() if debug: debug_fd.write("End process_file\n")
def run_test_class_multiple(rpt, mod, name, ob, test_order): currently_running_test_name.append(name) # print "PUSHED",name pycode.snarf_stdout() class_start_time = time.time() print "MULTIPLE" class_status = 'P' exception_str = None # find the test methods on the class object l = locate_test_methods(ob, test_order) # for each test method on the object for f_name, f_ob in l: if debug: debug_fd.write('run_test_class: test method: %s %s\n' % (f_name, str(f_ob))) try: # bug: stdout and exceptions go to the class, not the test class_ob = ob() # we have them so it is easy to convert tests back/forth class_ob.class_tda = {} class_ob.class_tra = {} # class setup is run once after the object init class_setup = getattr(class_ob, 'classSetUp', None) if class_setup: class_setup() # run the test method run_test_method(name, class_ob, f_name, f_ob, rpt) # exceptions that came out of handling the class, but not one of the test methods except AssertionError: class_status = 'F' traceback.print_exc() except: exception_str = get_exception_str() class_status = 'E' traceback.print_exc() try: # bug: stdout and exceptions go to the class, not the test # optional teardown class_teardown = getattr(class_ob, 'classTearDown', None) if class_teardown: class_teardown() except: exception_str = get_exception_str() class_status = 'E' traceback.print_exc() # this is the end of everything relating to the class. class_end_time = time.time() class_log = pycode.end_snarf_stdout() # it really doesn't make sense to say there is an attribute for # the class, when we have made many class objects, each with separate # attributes tda = {} tra = {} if exception_str is not None: tra['exception'] = exception_str gen_report(rpt, name, class_status, class_start_time, class_end_time, tda, tra, class_log)
def run_test_class_single(rpt, mod, name, ob, test_order): currently_running_test_name.append(name) # print "PUSHED",name pycode.snarf_stdout() class_start_time = time.time() class_status = 'P' exception_str = None # find the test methods on the class object l = locate_test_methods(ob, test_order) # instantiate the object; bail out early if we can't try: class_ob = ob() except: exception_str = get_exception_str() traceback.print_exc() # really nothing more we can do... gen_report(rpt, name, 'E', class_start_time, time.time(), {}, {'exception': exception_str}, pycode.end_snarf_stdout()) return # make sure the class attribute dictionaries exist class_ob.class_tda = getattr(class_ob, 'class_tda', {}) class_ob.class_tra = getattr(class_ob, 'class_tra', {}) try: # class setup is run once after the object init class_setup = getattr(class_ob, 'classSetUp', None) if class_setup: class_setup() # for each test method on the object for f_name, f_ob in l: if debug: debug_fd.write('run_test_class: test method: %s %s\n' % (f_name, str(f_ob))) # run the test method run_test_method(name, class_ob, f_name, f_ob, rpt) # exceptions that came out of handling the class, but not one of the test methods except AssertionError: class_status = 'F' traceback.print_exc() except: exception_str = get_exception_str() class_status = 'E' traceback.print_exc() try: # optional teardown class_teardown = getattr(class_ob, 'classTearDown', None) if class_teardown: class_teardown() except: exception_str = get_exception_str() class_status = 'E' traceback.print_exc() # this is the end of everything relating to the class. class_end_time = time.time() class_log = pycode.end_snarf_stdout() tda = getattr(class_ob, 'class_tda', {}) tra = getattr(class_ob, 'class_tra', {}) if exception_str is not None: tra['exception'] = exception_str gen_report(rpt, name, class_status, class_start_time, class_end_time, tda, tra, class_log)
def run_test_method(name, class_ob, f_name, f_ob, rpt): full_test_name = name + '.' + f_name currently_running_test_name.append(full_test_name) # print "PUSHED X",full_test_name pycode.snarf_stdout() fn_start_time = time.time() # clear the test attributes class_ob.tda = {} class_ob.tra = {} exception_str = None if getattr(f_ob, '__disable__', False): fn_status = 'D' else: # call the test method try: # call setUp if it is there setup = getattr(class_ob, 'setUp', None) if setup: setup() # call the test method f_ob(class_ob) # pass if we managed to return fn_status = 'P' except AssertionError: fn_status = 'F' traceback.print_exc() except: exception_str = get_exception_str() fn_status = 'E' traceback.print_exc() try: # call tearDown if it is there teardown = getattr(class_ob, 'tearDown', None) if teardown: teardown() except: print 'exception in teardown' exception_str = get_exception_str() fn_status = 'E' traceback.print_exc() fn_end_time = time.time() fn_log = pycode.end_snarf_stdout() tda = getattr(class_ob, 'class_tda', {}).copy() tda.update(getattr(class_ob, 'tda', {})) tra = getattr(class_ob, 'class_tra', {}).copy() tra.update(getattr(class_ob, 'tra', {})) if exception_str is not None: tra['exception'] = exception_str gen_report(rpt, full_test_name, fn_status, fn_start_time, fn_end_time, tda, tra, fn_log)
def main(args): # We want to gather everything that happens into the test report. # Individual tests will suck up their own stdout, so it will # not end up in the output that belongs to the file. pycode.snarf_stdout() # status is pass unless something else happens file_status = 'P' # No arg processing because pandokia left everything we need # in the environment. filename = os.environ['PDK_FILE'] # The module name is the basename of the file, without the extension. module_name = os.path.basename(filename) module_name = os.path.splitext(module_name)[0] file_start_time = time.time() if no_unittest2: print("%s Cannot import unittest2" % __file__) print(e) for x in sys.path: print(" %s" % x) file_status = 'E' else: # unittest2 is in very early stages of development. Cry if we # don't see the version we expect, because there may be incompatible # changes in the future. if unittest2.__version__ not in unittest2_versions: print( 'THIS IS NOT THE VERSION OF unittest2 THAT THE PANDOKIA RUNNER WAS WRITTEN FOR' ) print('HAVE %s' % unittest2.__version__) print('EXPECT ONE OF %s' % unittest2_versions) file_status = 'E' # to draw attention try: module = imp.load_source(module_name, filename) # This is a trick to pass a value to the initializer # pdk_test_result. It would be hard to go through channels # because unittest2 does not have a concept for this particular # data. I happen to know that it only makes a single TestRunner # object, so this is ok to do. pdk_runner.fixed_filename = module_name TestProgram( # module must be a loaded module to run tests from module=module, # argv must be a list with at least one element because # the TestProgram arg processing will try to read through # it whether we need it to or not. argv=['nop'], # provide it with our test runner, so it writes pandokia # logs instead of the default stuff to stdout testRunner=pdk_runner, # prevent it trying to exit when it is done exit=False, ) # Yes, the whole file can fail or error. This happens either # on import or when instantiating TestCase objects. except AssertionError: file_status = 'F' traceback.print_exc() except: file_status = 'E' traceback.print_exc() file_end_time = time.time() log = pycode.end_snarf_stdout() # We do not create the pandokia log entry object until after # everything is done. Down inside unittest2, our code is going # to open the same log file. It will close it before returning, # so we can open it here without conflicting. rpt = pycode.reporter(filename) # the name for the report on the file as a whole is derived from # the file name. the report object is already set up to do this, # so we do not need to provide any more parts of the test name. rpt.report(None, file_status, file_start_time, file_end_time, {}, {}, log) rpt.close()