1 #!/usr/bin/env python 2 3 import testlog_parser, sys, os, xml, glob, re 4 from table_formatter import * 5 from optparse import OptionParser 6 from operator import itemgetter, attrgetter 7 from summary import getSetName, alphanum_keyselector 8 import re 9 10 if __name__ == "__main__": 11 usage = "%prog <log_name>.xml [...]" 12 parser = OptionParser(usage = usage) 13 14 parser.add_option("-o", "--output", dest = "format", 15 help = "output results in text format (can be 'txt', 'html' or 'auto' - default)", 16 metavar = 'FMT', default = 'auto') 17 18 parser.add_option("--failed-only", action = "store_true", dest = "failedOnly", 19 help = "print only failed tests", default = False) 20 21 (options, args) = parser.parse_args() 22 23 options.generateHtml = detectHtmlOutputType(options.format) 24 25 files = [] 26 testsuits = [] # testsuit module, name, time, num, flag for failed tests 27 overall_time = 0 28 29 seen = set() 30 for arg in args: 31 if ("*" in arg) or ("?" in arg): 32 flist = [os.path.abspath(f) for f in glob.glob(arg)] 33 flist = sorted(flist, key= lambda text: str(text).replace("M", "_")) 34 files.extend([ x for x in flist if x not in seen and not seen.add(x)]) 35 else: 36 fname = os.path.abspath(arg) 37 if fname not in seen and not seen.add(fname): 38 files.append(fname) 39 40 file = os.path.abspath(fname) 41 if not os.path.isfile(file): 42 sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep) 43 parser.print_help() 44 exit(0) 45 46 fname = os.path.basename(fname) 47 find_module_name = re.search(r'([^_]*)', fname) 48 module_name = find_module_name.group(0) 49 50 test_sets = [] 51 try: 52 tests = testlog_parser.parseLogFile(file) 53 if tests: 54 test_sets.append((os.path.basename(file), tests)) 55 except IOError as err: 56 sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep) 57 except xml.parsers.expat.ExpatError as err: 58 sys.stderr.write("ExpatError reading \"" + file + "\" - " + str(err) + os.linesep) 59 60 if not test_sets: 61 continue 62 63 # find matches 64 setsCount = len(test_sets) 65 test_cases = {} 66 67 name_extractor = lambda name: str(name) 68 69 for i in range(setsCount): 70 for case in test_sets[i][1]: 71 name = name_extractor(case) 72 if name not in test_cases: 73 test_cases[name] = [None] * setsCount 74 test_cases[name][i] = case 75 76 prevGroupName = None 77 suit_time = 0 78 suit_num = 0 79 fails_num = 0 80 for name in sorted(test_cases.iterkeys(), key=alphanum_keyselector): 81 cases = test_cases[name] 82 83 groupName = next(c for c in cases if c).shortName() 84 if groupName != prevGroupName: 85 if prevGroupName != None: 86 suit_time = suit_time/60 #from seconds to minutes 87 testsuits.append({'module': module_name, 'name': prevGroupName, \ 88 'time': suit_time, 'num': suit_num, 'failed': fails_num}) 89 overall_time += suit_time 90 suit_time = 0 91 suit_num = 0 92 fails_num = 0 93 prevGroupName = groupName 94 95 for i in range(setsCount): 96 case = cases[i] 97 if not case is None: 98 suit_num += 1 99 if case.get('status') == 'run': 100 suit_time += case.get('time') 101 if case.get('status') == 'failed': 102 fails_num += 1 103 104 # last testsuit processing 105 suit_time = suit_time/60 106 testsuits.append({'module': module_name, 'name': prevGroupName, \ 107 'time': suit_time, 'num': suit_num, 'failed': fails_num}) 108 overall_time += suit_time 109 110 if len(testsuits)==0: 111 exit(0) 112 113 tbl = table() 114 rows = 0 115 116 if not options.failedOnly: 117 tbl.newColumn('module', 'Module', align = 'left', cssclass = 'col_name') 118 tbl.newColumn('name', 'Testsuit', align = 'left', cssclass = 'col_name') 119 tbl.newColumn('time', 'Time (min)', align = 'center', cssclass = 'col_name') 120 tbl.newColumn('num', 'Num of tests', align = 'center', cssclass = 'col_name') 121 tbl.newColumn('failed', 'Failed', align = 'center', cssclass = 'col_name') 122 123 # rows 124 for suit in sorted(testsuits, key = lambda suit: suit['time'], reverse = True): 125 tbl.newRow() 126 tbl.newCell('module', suit['module']) 127 tbl.newCell('name', suit['name']) 128 tbl.newCell('time', formatValue(suit['time'], '', ''), suit['time']) 129 tbl.newCell('num', suit['num']) 130 if (suit['failed'] != 0): 131 tbl.newCell('failed', suit['failed']) 132 else: 133 tbl.newCell('failed', ' ') 134 rows += 1 135 136 else: 137 tbl.newColumn('module', 'Module', align = 'left', cssclass = 'col_name') 138 tbl.newColumn('name', 'Testsuit', align = 'left', cssclass = 'col_name') 139 tbl.newColumn('failed', 'Failed', align = 'center', cssclass = 'col_name') 140 141 # rows 142 for suit in sorted(testsuits, key = lambda suit: suit['time'], reverse = True): 143 if (suit['failed'] != 0): 144 tbl.newRow() 145 tbl.newCell('module', suit['module']) 146 tbl.newCell('name', suit['name']) 147 tbl.newCell('failed', suit['failed']) 148 rows += 1 149 150 # output table 151 if rows: 152 if options.generateHtml: 153 tbl.htmlPrintTable(sys.stdout) 154 htmlPrintFooter(sys.stdout) 155 else: 156 if not options.failedOnly: 157 print '\nOverall time: %.2f min\n' % overall_time 158 tbl.consolePrintTable(sys.stdout) 159 print 2 * '\n' 160