unittest_suite.py revision 656b3b8e1092a08bb60a059b09d1dbafadcbd037
1#!/usr/bin/python -u 2 3import os, sys, unittest, optparse 4import common 5from autotest_lib.utils import parallel 6from autotest_lib.client.common_lib.test_utils import unittest as custom_unittest 7 8parser = optparse.OptionParser() 9parser.add_option("-r", action="store", type="string", dest="start", 10 default='', 11 help="root directory to start running unittests") 12parser.add_option("--full", action="store_true", dest="full", default=False, 13 help="whether to run the shortened version of the test") 14parser.add_option("--debug", action="store_true", dest="debug", default=False, 15 help="run in debug mode") 16 17LONG_TESTS = set(( 18 'monitor_db_unittest.py', 19 'monitor_db_functional_test.py', 20 'monitor_db_cleanup_test.py', 21 'barrier_unittest.py', 22 'migrate_unittest.py', 23 'frontend_unittest.py', 24 'client_compilation_unittest.py', 25 'csv_encoder_unittest.py', 26 'rpc_interface_unittest.py', 27 'resources_test.py', 28 'logging_manager_test.py', 29 'models_test.py', 30 'serviceHandler_unittest.py', 31 )) 32 33ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) 34 35 36class TestFailure(Exception): pass 37 38 39def run_test(mod_names, options): 40 """ 41 @param mod_names: A list of individual parts of the module name to import 42 and run as a test suite. 43 @param options: optparse options. 44 """ 45 if not options.debug: 46 parallel.redirect_io() 47 48 print "Running %s" % '.'.join(mod_names) 49 mod = common.setup_modules.import_module(mod_names[-1], 50 '.'.join(mod_names[:-1])) 51 for ut_module in [unittest, custom_unittest]: 52 test = ut_module.defaultTestLoader.loadTestsFromModule(mod) 53 suite = ut_module.TestSuite(test) 54 runner = ut_module.TextTestRunner(verbosity=2) 55 result = runner.run(suite) 56 if result.errors or result.failures: 57 msg = '%s had %d failures and %d errors.' 58 msg %= '.'.join(mod_names), len(result.failures), len(result.errors) 59 raise TestFailure(msg) 60 61 62def find_and_run_tests(start, options): 63 """ 64 Find and run Python unittest suites below the given directory. Only look 65 in subdirectories of start that are actual importable Python modules. 66 67 @param start: The absolute directory to look for tests under. 68 @param options: optparse options. 69 """ 70 modules = [] 71 72 for dirpath, subdirs, filenames in os.walk(start): 73 # Only look in and below subdirectories that are python modules. 74 if '__init__.py' not in filenames: 75 if options.full: 76 for filename in filenames: 77 if filename.endswith('.pyc'): 78 os.unlink(os.path.join(dirpath, filename)) 79 # Skip all subdirectories below this one, it is not a module. 80 del subdirs[:] 81 if options.debug: 82 print 'Skipping', dirpath 83 continue # Skip this directory. 84 85 # Look for unittest files. 86 for fname in filenames: 87 if fname.endswith('_unittest.py') or fname.endswith('_test.py'): 88 if not options.full and fname in LONG_TESTS: 89 continue 90 path_no_py = os.path.join(dirpath, fname).rstrip('.py') 91 assert path_no_py.startswith(ROOT) 92 names = path_no_py[len(ROOT)+1:].split('/') 93 modules.append(['autotest_lib'] + names) 94 if options.debug: 95 print 'testing', path_no_py 96 97 if options.debug: 98 print 'Number of test modules found:', len(modules) 99 100 functions = {} 101 for module_names in modules: 102 # Create a function that'll test a particular module. module=module 103 # is a hack to force python to evaluate the params now. We then 104 # rename the function to make error reporting nicer. 105 run_module = lambda module=module_names: run_test(module, options) 106 name = '.'.join(module_names) 107 run_module.__name__ = name 108 functions[run_module] = set() 109 110 try: 111 dargs = {} 112 if options.debug: 113 dargs['max_simultaneous_procs'] = 1 114 pe = parallel.ParallelExecute(functions, **dargs) 115 pe.run_until_completion() 116 except parallel.ParallelError, err: 117 return err.errors 118 return [] 119 120 121def main(): 122 options, args = parser.parse_args() 123 if args: 124 parser.error('Unexpected argument(s): %s' % args) 125 parser.print_help() 126 sys.exit(1) 127 128 # Strip the arguments off the command line, so that the unit tests do not 129 # see them. 130 del sys.argv[1:] 131 132 absolute_start = os.path.join(ROOT, options.start) 133 errors = find_and_run_tests(absolute_start, options) 134 if errors: 135 print "%d tests resulted in an error/failure:" % len(errors) 136 for error in errors: 137 print "\t%s" % error 138 print "Rerun", sys.argv[0], "--debug to see the failure details." 139 sys.exit(1) 140 else: 141 print "All passed!" 142 sys.exit(0) 143 144 145if __name__ == "__main__": 146 main() 147