Skip to content

Commit 09d111e

Browse files
committed
[GR-14227] unittest_runner: track test stats, generated reports are not precise
PullRequest: graalpython/424
2 parents 480167b + 9a8ba1f commit 09d111e

File tree

1 file changed

+86
-9
lines changed

1 file changed

+86
-9
lines changed

graalpython/com.oracle.graal.python.test/src/python_unittests.py

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
PTRN_IMPORT_ERROR = re.compile(r".*cannot import name \'(?P<module>.*)\'.*", re.DOTALL)
7777
PTRN_REMOTE_HOST = re.compile(r"(?P<user>\w+)@(?P<host>[\w.]+):(?P<path>.+)")
7878
PTRN_VALID_CSV_NAME = re.compile(r"unittests-\d{4}-\d{2}-\d{2}.csv")
79+
PTRN_TEST_STATUS_INDIVIDUAL = re.compile(r"(?P<name>test[\w_]+ \(.+?\)) ... (?P<status>.+)")
80+
PTRN_TEST_STATUS_ERROR = re.compile(r"(?P<status>.+): (?P<name>test[\w_]+ \(.+?\))")
7981

8082

8183
# ----------------------------------------------------------------------------------------------------------------------
@@ -216,6 +218,13 @@ def read_csv(path):
216218
return rows
217219

218220

221+
class TestStatus(object):
222+
ERROR = 'error'
223+
FAIL = 'fail'
224+
SKIPPED = 'skipped'
225+
OK = 'ok'
226+
227+
219228
# ----------------------------------------------------------------------------------------------------------------------
220229
#
221230
# result (output processing)
@@ -224,35 +233,88 @@ def read_csv(path):
224233
class StatEntry(object):
225234
def __init__(self):
226235
self.num_tests = -1
227-
self.num_errors = -1
228-
self.num_fails = -1
229-
self.num_skipped = -1
236+
# reported stats
237+
self._num_errors = -1
238+
self._num_fails = -1
239+
self._num_skipped = -1
240+
# tracked stats
241+
self._tracked = False
242+
243+
def _reset(self):
244+
self._num_fails = 0
245+
self._num_errors = 0
246+
self._num_skipped = 0
230247

231248
def all_ok(self):
232-
self.num_fails = 0
233-
self.num_errors = 0
234-
self.num_skipped = 0
249+
self._reset()
250+
251+
@property
252+
def num_errors(self):
253+
return self._num_errors
254+
255+
@num_errors.setter
256+
def num_errors(self, value):
257+
if not self._tracked:
258+
self._num_errors = value
259+
260+
@property
261+
def num_fails(self):
262+
return self._num_fails
263+
264+
@num_fails.setter
265+
def num_fails(self, value):
266+
if not self._tracked:
267+
self._num_fails = value
268+
269+
@property
270+
def num_skipped(self):
271+
return self._num_skipped
272+
273+
@num_skipped.setter
274+
def num_skipped(self, value):
275+
if not self._tracked:
276+
self._num_skipped = value
235277

236278
@property
237279
def num_passes(self):
238280
if self.num_tests > 0:
239-
return self.num_tests - (self.num_fails + self.num_errors + self.num_skipped)
281+
return self.num_tests - (self._num_fails + self._num_errors + self._num_skipped)
240282
return -1
241283

284+
def update(self, test_detailed_stats):
285+
if len(test_detailed_stats) > 0:
286+
self._tracked = True
287+
self._reset()
288+
for test, stats in test_detailed_stats.items():
289+
stats = {s.lower() for s in stats}
290+
if TestStatus.ERROR in stats:
291+
self._num_errors += 1
292+
elif TestStatus.FAIL in stats:
293+
self._num_fails += 1
294+
else:
295+
for s in stats:
296+
if s.startswith(TestStatus.SKIPPED):
297+
self._num_skipped += 1
298+
break
299+
242300

243301
def process_output(output_lines):
244302
if isinstance(output_lines, str):
245303
output_lines = output_lines.split("\n")
246304

247305
unittests = []
306+
# stats tracked per unittest
307+
unittest_tests = defaultdict(list)
248308
error_messages = defaultdict(set)
249309
java_exceptions = defaultdict(set)
250310
stats = defaultdict(StatEntry)
251311

252312
for line in output_lines:
253313
match = re.match(PTRN_UNITTEST, line)
254314
if match:
255-
unittests.append(match.group('unittest'))
315+
unittest = match.group('unittest')
316+
unittests.append(unittest)
317+
unittest_tests.clear()
256318
continue
257319

258320
# extract python reported python error messages
@@ -268,6 +330,16 @@ def process_output(output_lines):
268330
continue
269331

270332
# stats
333+
# tracking stats
334+
match = re.match(PTRN_TEST_STATUS_INDIVIDUAL, line)
335+
if not match:
336+
match = re.match(PTRN_TEST_STATUS_ERROR, line)
337+
if match:
338+
name = match.group('name')
339+
status = match.group('status')
340+
unittest_tests[name].append(status)
341+
continue
342+
271343
if line.strip() == 'OK':
272344
stats[unittests[-1]].all_ok()
273345
continue
@@ -286,6 +358,8 @@ def process_output(output_lines):
286358
match = re.match(PTRN_NUM_TESTS, line)
287359
if match:
288360
stats[unittests[-1]].num_tests = int(match.group('num_tests'))
361+
stats[unittests[-1]].update(unittest_tests)
362+
unittest_tests.clear()
289363
continue
290364

291365
match = re.match(PTRN_FAILED, line)
@@ -299,6 +373,7 @@ def process_output(output_lines):
299373
stats[unittests[-1]].num_fails = int(fails) if fails else 0
300374
stats[unittests[-1]].num_errors = int(errs) if errs else 0
301375
stats[unittests[-1]].num_skipped = int(skipped) if skipped else 0
376+
continue
302377

303378
return unittests, error_messages, java_exceptions, stats
304379

@@ -712,6 +787,8 @@ def main(prog, args):
712787
parser = argparse.ArgumentParser(prog=prog,
713788
description="Run the standard python unittests.")
714789
parser.add_argument("-v", "--verbose", help="Verbose output.", action="store_true")
790+
parser.add_argument("-n", "--no_cpython", help="Do not run the tests with cpython (for comparison).",
791+
action="store_true")
715792
parser.add_argument("-l", "--limit", help="Limit the number of unittests to run.", default=None, type=int)
716793
parser.add_argument("-t", "--tests_path", help="Unittests path.", default=PATH_UNITTESTS)
717794
parser.add_argument("-T", "--timeout", help="Timeout per unittest run.", default=TIMEOUT, type=int)
@@ -754,7 +831,7 @@ def _fmt(t):
754831
unittests = get_unittests(flags.tests_path, limit=flags.limit, skip_tests=skip_tests)
755832

756833
# get cpython stats
757-
if not flags.gate:
834+
if not flags.gate and not flags.no_cpython:
758835
log(HR)
759836
log("[INFO] get cpython stats")
760837
cpy_results = run_unittests(unittests, 60 * 5, with_cpython=True)

0 commit comments

Comments
 (0)