1*cda5da8dSAndroid Build Coastguard Worker"""Running tests""" 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard Workerimport sys 4*cda5da8dSAndroid Build Coastguard Workerimport time 5*cda5da8dSAndroid Build Coastguard Workerimport warnings 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Workerfrom . import result 8*cda5da8dSAndroid Build Coastguard Workerfrom .case import _SubTest 9*cda5da8dSAndroid Build Coastguard Workerfrom .signals import registerResult 10*cda5da8dSAndroid Build Coastguard Worker 11*cda5da8dSAndroid Build Coastguard Worker__unittest = True 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Worker 14*cda5da8dSAndroid Build Coastguard Workerclass _WritelnDecorator(object): 15*cda5da8dSAndroid Build Coastguard Worker """Used to decorate file-like objects with a handy 'writeln' method""" 16*cda5da8dSAndroid Build Coastguard Worker def __init__(self,stream): 17*cda5da8dSAndroid Build Coastguard Worker self.stream = stream 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard Worker def __getattr__(self, attr): 20*cda5da8dSAndroid Build Coastguard Worker if attr in ('stream', '__getstate__'): 21*cda5da8dSAndroid Build Coastguard Worker raise AttributeError(attr) 22*cda5da8dSAndroid Build Coastguard Worker return getattr(self.stream,attr) 23*cda5da8dSAndroid Build Coastguard Worker 24*cda5da8dSAndroid Build Coastguard Worker def writeln(self, arg=None): 25*cda5da8dSAndroid Build Coastguard Worker if arg: 26*cda5da8dSAndroid Build Coastguard Worker self.write(arg) 27*cda5da8dSAndroid Build Coastguard Worker self.write('\n') # text-mode streams translate to \r\n if needed 28*cda5da8dSAndroid Build Coastguard Worker 29*cda5da8dSAndroid Build Coastguard Worker 30*cda5da8dSAndroid Build Coastguard Workerclass TextTestResult(result.TestResult): 31*cda5da8dSAndroid Build Coastguard Worker """A test result class that can print formatted text results to a stream. 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker Used by TextTestRunner. 34*cda5da8dSAndroid Build Coastguard Worker """ 35*cda5da8dSAndroid Build Coastguard Worker separator1 = '=' * 70 36*cda5da8dSAndroid Build Coastguard Worker separator2 = '-' * 70 37*cda5da8dSAndroid Build Coastguard Worker 38*cda5da8dSAndroid Build Coastguard Worker def __init__(self, stream, descriptions, verbosity): 39*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).__init__(stream, descriptions, verbosity) 40*cda5da8dSAndroid Build Coastguard Worker self.stream = stream 41*cda5da8dSAndroid Build Coastguard Worker self.showAll = verbosity > 1 42*cda5da8dSAndroid Build Coastguard Worker self.dots = verbosity == 1 43*cda5da8dSAndroid Build Coastguard Worker self.descriptions = descriptions 44*cda5da8dSAndroid Build Coastguard Worker self._newline = True 45*cda5da8dSAndroid Build Coastguard Worker 46*cda5da8dSAndroid Build Coastguard Worker def getDescription(self, test): 47*cda5da8dSAndroid Build Coastguard Worker doc_first_line = test.shortDescription() 48*cda5da8dSAndroid Build Coastguard Worker if self.descriptions and doc_first_line: 49*cda5da8dSAndroid Build Coastguard Worker return '\n'.join((str(test), doc_first_line)) 50*cda5da8dSAndroid Build Coastguard Worker else: 51*cda5da8dSAndroid Build Coastguard Worker return str(test) 52*cda5da8dSAndroid Build Coastguard Worker 53*cda5da8dSAndroid Build Coastguard Worker def startTest(self, test): 54*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).startTest(test) 55*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 56*cda5da8dSAndroid Build Coastguard Worker self.stream.write(self.getDescription(test)) 57*cda5da8dSAndroid Build Coastguard Worker self.stream.write(" ... ") 58*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 59*cda5da8dSAndroid Build Coastguard Worker self._newline = False 60*cda5da8dSAndroid Build Coastguard Worker 61*cda5da8dSAndroid Build Coastguard Worker def _write_status(self, test, status): 62*cda5da8dSAndroid Build Coastguard Worker is_subtest = isinstance(test, _SubTest) 63*cda5da8dSAndroid Build Coastguard Worker if is_subtest or self._newline: 64*cda5da8dSAndroid Build Coastguard Worker if not self._newline: 65*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln() 66*cda5da8dSAndroid Build Coastguard Worker if is_subtest: 67*cda5da8dSAndroid Build Coastguard Worker self.stream.write(" ") 68*cda5da8dSAndroid Build Coastguard Worker self.stream.write(self.getDescription(test)) 69*cda5da8dSAndroid Build Coastguard Worker self.stream.write(" ... ") 70*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln(status) 71*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 72*cda5da8dSAndroid Build Coastguard Worker self._newline = True 73*cda5da8dSAndroid Build Coastguard Worker 74*cda5da8dSAndroid Build Coastguard Worker def addSubTest(self, test, subtest, err): 75*cda5da8dSAndroid Build Coastguard Worker if err is not None: 76*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 77*cda5da8dSAndroid Build Coastguard Worker if issubclass(err[0], subtest.failureException): 78*cda5da8dSAndroid Build Coastguard Worker self._write_status(subtest, "FAIL") 79*cda5da8dSAndroid Build Coastguard Worker else: 80*cda5da8dSAndroid Build Coastguard Worker self._write_status(subtest, "ERROR") 81*cda5da8dSAndroid Build Coastguard Worker elif self.dots: 82*cda5da8dSAndroid Build Coastguard Worker if issubclass(err[0], subtest.failureException): 83*cda5da8dSAndroid Build Coastguard Worker self.stream.write('F') 84*cda5da8dSAndroid Build Coastguard Worker else: 85*cda5da8dSAndroid Build Coastguard Worker self.stream.write('E') 86*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 87*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).addSubTest(test, subtest, err) 88*cda5da8dSAndroid Build Coastguard Worker 89*cda5da8dSAndroid Build Coastguard Worker def addSuccess(self, test): 90*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).addSuccess(test) 91*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 92*cda5da8dSAndroid Build Coastguard Worker self._write_status(test, "ok") 93*cda5da8dSAndroid Build Coastguard Worker elif self.dots: 94*cda5da8dSAndroid Build Coastguard Worker self.stream.write('.') 95*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 96*cda5da8dSAndroid Build Coastguard Worker 97*cda5da8dSAndroid Build Coastguard Worker def addError(self, test, err): 98*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).addError(test, err) 99*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 100*cda5da8dSAndroid Build Coastguard Worker self._write_status(test, "ERROR") 101*cda5da8dSAndroid Build Coastguard Worker elif self.dots: 102*cda5da8dSAndroid Build Coastguard Worker self.stream.write('E') 103*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 104*cda5da8dSAndroid Build Coastguard Worker 105*cda5da8dSAndroid Build Coastguard Worker def addFailure(self, test, err): 106*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).addFailure(test, err) 107*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 108*cda5da8dSAndroid Build Coastguard Worker self._write_status(test, "FAIL") 109*cda5da8dSAndroid Build Coastguard Worker elif self.dots: 110*cda5da8dSAndroid Build Coastguard Worker self.stream.write('F') 111*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 112*cda5da8dSAndroid Build Coastguard Worker 113*cda5da8dSAndroid Build Coastguard Worker def addSkip(self, test, reason): 114*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).addSkip(test, reason) 115*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 116*cda5da8dSAndroid Build Coastguard Worker self._write_status(test, "skipped {0!r}".format(reason)) 117*cda5da8dSAndroid Build Coastguard Worker elif self.dots: 118*cda5da8dSAndroid Build Coastguard Worker self.stream.write("s") 119*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 120*cda5da8dSAndroid Build Coastguard Worker 121*cda5da8dSAndroid Build Coastguard Worker def addExpectedFailure(self, test, err): 122*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).addExpectedFailure(test, err) 123*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 124*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln("expected failure") 125*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 126*cda5da8dSAndroid Build Coastguard Worker elif self.dots: 127*cda5da8dSAndroid Build Coastguard Worker self.stream.write("x") 128*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 129*cda5da8dSAndroid Build Coastguard Worker 130*cda5da8dSAndroid Build Coastguard Worker def addUnexpectedSuccess(self, test): 131*cda5da8dSAndroid Build Coastguard Worker super(TextTestResult, self).addUnexpectedSuccess(test) 132*cda5da8dSAndroid Build Coastguard Worker if self.showAll: 133*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln("unexpected success") 134*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 135*cda5da8dSAndroid Build Coastguard Worker elif self.dots: 136*cda5da8dSAndroid Build Coastguard Worker self.stream.write("u") 137*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 138*cda5da8dSAndroid Build Coastguard Worker 139*cda5da8dSAndroid Build Coastguard Worker def printErrors(self): 140*cda5da8dSAndroid Build Coastguard Worker if self.dots or self.showAll: 141*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln() 142*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 143*cda5da8dSAndroid Build Coastguard Worker self.printErrorList('ERROR', self.errors) 144*cda5da8dSAndroid Build Coastguard Worker self.printErrorList('FAIL', self.failures) 145*cda5da8dSAndroid Build Coastguard Worker unexpectedSuccesses = getattr(self, 'unexpectedSuccesses', ()) 146*cda5da8dSAndroid Build Coastguard Worker if unexpectedSuccesses: 147*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln(self.separator1) 148*cda5da8dSAndroid Build Coastguard Worker for test in unexpectedSuccesses: 149*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln(f"UNEXPECTED SUCCESS: {self.getDescription(test)}") 150*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 151*cda5da8dSAndroid Build Coastguard Worker 152*cda5da8dSAndroid Build Coastguard Worker def printErrorList(self, flavour, errors): 153*cda5da8dSAndroid Build Coastguard Worker for test, err in errors: 154*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln(self.separator1) 155*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln("%s: %s" % (flavour,self.getDescription(test))) 156*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln(self.separator2) 157*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln("%s" % err) 158*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 159*cda5da8dSAndroid Build Coastguard Worker 160*cda5da8dSAndroid Build Coastguard Worker 161*cda5da8dSAndroid Build Coastguard Workerclass TextTestRunner(object): 162*cda5da8dSAndroid Build Coastguard Worker """A test runner class that displays results in textual form. 163*cda5da8dSAndroid Build Coastguard Worker 164*cda5da8dSAndroid Build Coastguard Worker It prints out the names of tests as they are run, errors as they 165*cda5da8dSAndroid Build Coastguard Worker occur, and a summary of the results at the end of the test run. 166*cda5da8dSAndroid Build Coastguard Worker """ 167*cda5da8dSAndroid Build Coastguard Worker resultclass = TextTestResult 168*cda5da8dSAndroid Build Coastguard Worker 169*cda5da8dSAndroid Build Coastguard Worker def __init__(self, stream=None, descriptions=True, verbosity=1, 170*cda5da8dSAndroid Build Coastguard Worker failfast=False, buffer=False, resultclass=None, warnings=None, 171*cda5da8dSAndroid Build Coastguard Worker *, tb_locals=False): 172*cda5da8dSAndroid Build Coastguard Worker """Construct a TextTestRunner. 173*cda5da8dSAndroid Build Coastguard Worker 174*cda5da8dSAndroid Build Coastguard Worker Subclasses should accept **kwargs to ensure compatibility as the 175*cda5da8dSAndroid Build Coastguard Worker interface changes. 176*cda5da8dSAndroid Build Coastguard Worker """ 177*cda5da8dSAndroid Build Coastguard Worker if stream is None: 178*cda5da8dSAndroid Build Coastguard Worker stream = sys.stderr 179*cda5da8dSAndroid Build Coastguard Worker self.stream = _WritelnDecorator(stream) 180*cda5da8dSAndroid Build Coastguard Worker self.descriptions = descriptions 181*cda5da8dSAndroid Build Coastguard Worker self.verbosity = verbosity 182*cda5da8dSAndroid Build Coastguard Worker self.failfast = failfast 183*cda5da8dSAndroid Build Coastguard Worker self.buffer = buffer 184*cda5da8dSAndroid Build Coastguard Worker self.tb_locals = tb_locals 185*cda5da8dSAndroid Build Coastguard Worker self.warnings = warnings 186*cda5da8dSAndroid Build Coastguard Worker if resultclass is not None: 187*cda5da8dSAndroid Build Coastguard Worker self.resultclass = resultclass 188*cda5da8dSAndroid Build Coastguard Worker 189*cda5da8dSAndroid Build Coastguard Worker def _makeResult(self): 190*cda5da8dSAndroid Build Coastguard Worker return self.resultclass(self.stream, self.descriptions, self.verbosity) 191*cda5da8dSAndroid Build Coastguard Worker 192*cda5da8dSAndroid Build Coastguard Worker def run(self, test): 193*cda5da8dSAndroid Build Coastguard Worker "Run the given test case or test suite." 194*cda5da8dSAndroid Build Coastguard Worker result = self._makeResult() 195*cda5da8dSAndroid Build Coastguard Worker registerResult(result) 196*cda5da8dSAndroid Build Coastguard Worker result.failfast = self.failfast 197*cda5da8dSAndroid Build Coastguard Worker result.buffer = self.buffer 198*cda5da8dSAndroid Build Coastguard Worker result.tb_locals = self.tb_locals 199*cda5da8dSAndroid Build Coastguard Worker with warnings.catch_warnings(): 200*cda5da8dSAndroid Build Coastguard Worker if self.warnings: 201*cda5da8dSAndroid Build Coastguard Worker # if self.warnings is set, use it to filter all the warnings 202*cda5da8dSAndroid Build Coastguard Worker warnings.simplefilter(self.warnings) 203*cda5da8dSAndroid Build Coastguard Worker # if the filter is 'default' or 'always', special-case the 204*cda5da8dSAndroid Build Coastguard Worker # warnings from the deprecated unittest methods to show them 205*cda5da8dSAndroid Build Coastguard Worker # no more than once per module, because they can be fairly 206*cda5da8dSAndroid Build Coastguard Worker # noisy. The -Wd and -Wa flags can be used to bypass this 207*cda5da8dSAndroid Build Coastguard Worker # only when self.warnings is None. 208*cda5da8dSAndroid Build Coastguard Worker if self.warnings in ['default', 'always']: 209*cda5da8dSAndroid Build Coastguard Worker warnings.filterwarnings('module', 210*cda5da8dSAndroid Build Coastguard Worker category=DeprecationWarning, 211*cda5da8dSAndroid Build Coastguard Worker message=r'Please use assert\w+ instead.') 212*cda5da8dSAndroid Build Coastguard Worker startTime = time.perf_counter() 213*cda5da8dSAndroid Build Coastguard Worker startTestRun = getattr(result, 'startTestRun', None) 214*cda5da8dSAndroid Build Coastguard Worker if startTestRun is not None: 215*cda5da8dSAndroid Build Coastguard Worker startTestRun() 216*cda5da8dSAndroid Build Coastguard Worker try: 217*cda5da8dSAndroid Build Coastguard Worker test(result) 218*cda5da8dSAndroid Build Coastguard Worker finally: 219*cda5da8dSAndroid Build Coastguard Worker stopTestRun = getattr(result, 'stopTestRun', None) 220*cda5da8dSAndroid Build Coastguard Worker if stopTestRun is not None: 221*cda5da8dSAndroid Build Coastguard Worker stopTestRun() 222*cda5da8dSAndroid Build Coastguard Worker stopTime = time.perf_counter() 223*cda5da8dSAndroid Build Coastguard Worker timeTaken = stopTime - startTime 224*cda5da8dSAndroid Build Coastguard Worker result.printErrors() 225*cda5da8dSAndroid Build Coastguard Worker if hasattr(result, 'separator2'): 226*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln(result.separator2) 227*cda5da8dSAndroid Build Coastguard Worker run = result.testsRun 228*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln("Ran %d test%s in %.3fs" % 229*cda5da8dSAndroid Build Coastguard Worker (run, run != 1 and "s" or "", timeTaken)) 230*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln() 231*cda5da8dSAndroid Build Coastguard Worker 232*cda5da8dSAndroid Build Coastguard Worker expectedFails = unexpectedSuccesses = skipped = 0 233*cda5da8dSAndroid Build Coastguard Worker try: 234*cda5da8dSAndroid Build Coastguard Worker results = map(len, (result.expectedFailures, 235*cda5da8dSAndroid Build Coastguard Worker result.unexpectedSuccesses, 236*cda5da8dSAndroid Build Coastguard Worker result.skipped)) 237*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 238*cda5da8dSAndroid Build Coastguard Worker pass 239*cda5da8dSAndroid Build Coastguard Worker else: 240*cda5da8dSAndroid Build Coastguard Worker expectedFails, unexpectedSuccesses, skipped = results 241*cda5da8dSAndroid Build Coastguard Worker 242*cda5da8dSAndroid Build Coastguard Worker infos = [] 243*cda5da8dSAndroid Build Coastguard Worker if not result.wasSuccessful(): 244*cda5da8dSAndroid Build Coastguard Worker self.stream.write("FAILED") 245*cda5da8dSAndroid Build Coastguard Worker failed, errored = len(result.failures), len(result.errors) 246*cda5da8dSAndroid Build Coastguard Worker if failed: 247*cda5da8dSAndroid Build Coastguard Worker infos.append("failures=%d" % failed) 248*cda5da8dSAndroid Build Coastguard Worker if errored: 249*cda5da8dSAndroid Build Coastguard Worker infos.append("errors=%d" % errored) 250*cda5da8dSAndroid Build Coastguard Worker else: 251*cda5da8dSAndroid Build Coastguard Worker self.stream.write("OK") 252*cda5da8dSAndroid Build Coastguard Worker if skipped: 253*cda5da8dSAndroid Build Coastguard Worker infos.append("skipped=%d" % skipped) 254*cda5da8dSAndroid Build Coastguard Worker if expectedFails: 255*cda5da8dSAndroid Build Coastguard Worker infos.append("expected failures=%d" % expectedFails) 256*cda5da8dSAndroid Build Coastguard Worker if unexpectedSuccesses: 257*cda5da8dSAndroid Build Coastguard Worker infos.append("unexpected successes=%d" % unexpectedSuccesses) 258*cda5da8dSAndroid Build Coastguard Worker if infos: 259*cda5da8dSAndroid Build Coastguard Worker self.stream.writeln(" (%s)" % (", ".join(infos),)) 260*cda5da8dSAndroid Build Coastguard Worker else: 261*cda5da8dSAndroid Build Coastguard Worker self.stream.write("\n") 262*cda5da8dSAndroid Build Coastguard Worker self.stream.flush() 263*cda5da8dSAndroid Build Coastguard Worker return result 264