bpo-4080: unittest durations (#12271)

This commit is contained in:
Giampaolo Rodola 2023-04-03 00:12:51 +02:00 committed by GitHub
parent a0305c5fdf
commit 6883007a86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 227 additions and 34 deletions

View file

@ -35,13 +35,16 @@ class TextTestResult(result.TestResult):
separator1 = '=' * 70
separator2 = '-' * 70
def __init__(self, stream, descriptions, verbosity):
def __init__(self, stream, descriptions, verbosity, *, durations=None):
"""Construct a TextTestResult. Subclasses should accept **kwargs
to ensure compatibility as the interface changes."""
super(TextTestResult, self).__init__(stream, descriptions, verbosity)
self.stream = stream
self.showAll = verbosity > 1
self.dots = verbosity == 1
self.descriptions = descriptions
self._newline = True
self.durations = durations
def getDescription(self, test):
doc_first_line = test.shortDescription()
@ -168,7 +171,7 @@ class TextTestRunner(object):
def __init__(self, stream=None, descriptions=True, verbosity=1,
failfast=False, buffer=False, resultclass=None, warnings=None,
*, tb_locals=False):
*, tb_locals=False, durations=None):
"""Construct a TextTestRunner.
Subclasses should accept **kwargs to ensure compatibility as the
@ -182,12 +185,41 @@ class TextTestRunner(object):
self.failfast = failfast
self.buffer = buffer
self.tb_locals = tb_locals
self.durations = durations
self.warnings = warnings
if resultclass is not None:
self.resultclass = resultclass
def _makeResult(self):
return self.resultclass(self.stream, self.descriptions, self.verbosity)
try:
return self.resultclass(self.stream, self.descriptions,
self.verbosity, durations=self.durations)
except TypeError:
# didn't accept the durations argument
return self.resultclass(self.stream, self.descriptions,
self.verbosity)
def _printDurations(self, result):
if not result.collectedDurations:
return
ls = sorted(result.collectedDurations, key=lambda x: x[1],
reverse=True)
if self.durations > 0:
ls = ls[:self.durations]
self.stream.writeln("Slowest test durations")
if hasattr(result, 'separator2'):
self.stream.writeln(result.separator2)
hidden = False
for test, elapsed in ls:
if self.verbosity < 2 and elapsed < 0.001:
hidden = True
continue
self.stream.writeln("%-10s %s" % ("%.3fs" % elapsed, test))
if hidden:
self.stream.writeln("\n(durations < 0.001s were hidden; "
"use -v to show these durations)")
else:
self.stream.writeln("")
def run(self, test):
"Run the given test case or test suite."
@ -213,8 +245,12 @@ class TextTestRunner(object):
stopTime = time.perf_counter()
timeTaken = stopTime - startTime
result.printErrors()
if self.durations is not None:
self._printDurations(result)
if hasattr(result, 'separator2'):
self.stream.writeln(result.separator2)
run = result.testsRun
self.stream.writeln("Ran %d test%s in %.3fs" %
(run, run != 1 and "s" or "", timeTaken))