summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorDimitrios Apostolou <jimis@qt.io>2022-01-26 20:56:35 +0100
committerDimitrios Apostolou <jimis@qt.io>2022-01-30 01:00:35 +0100
commitb013f9408691cceb7e8e7617bcaee0c0fc02c241 (patch)
tree1b207cf0fe76a9966123c1eba8c7780820a444da /util
parentb4d9d5c89c82e47b03de22ba896ad6c0474bcf5a (diff)
Write XML test log files even for the flaky test re-runs
Previously the qt-testrunner script was avoiding to write XML log files for the flaky test re-runs, since parsing them always provides limited information about what went wrong (for example unparseable files) and might miss issues completely (for example a crashed test might not even write a log file), or even mislead if multiple different data points about a single testcase end up into the database.. But currently Coin is the system that uploads test information to the testresults database and expects to find such log files in an attempt to send as much information as possible regarding failures. Re-enabling these log files will allow Coin to deduce as much information as possible about the test runs. This is a temporary step at least, until the test-uploading logic is separated from Coin. Then it will be easier to find the full information about what happened with flaky or crashed tests by special logs from qt-testrunner.py, which is the test re-running orchestrator and therefore has more knowledge about what went wrong. Fixes: QTQAINFRA-4754 Change-Id: I69e4469cbe6c0a6ca5b2473eaf8d034632564342 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Toni Saario <toni.saario@qt.io> Reviewed-by: Simo Fält <simo.falt@qt.io>
Diffstat (limited to 'util')
-rwxr-xr-xutil/testrunner/qt-testrunner.py26
1 files changed, 20 insertions, 6 deletions
diff --git a/util/testrunner/qt-testrunner.py b/util/testrunner/qt-testrunner.py
index d0d54f054c..20ef2ccbb7 100755
--- a/util/testrunner/qt-testrunner.py
+++ b/util/testrunner/qt-testrunner.py
@@ -79,6 +79,7 @@ import argparse
import subprocess
import os
import traceback
+import time
import timeit
import xml.etree.ElementTree as ET
import logging as L
@@ -241,6 +242,10 @@ def run_test(arg_list: List[str], **kwargs):
return proc
+def unique_filename(test_basename: str) -> str:
+ timestamp = round(time.time() * 1000)
+ return f"{test_basename}-{timestamp}.xml"
+
# Returns tuple: (exit_code, xml_logfile)
def run_full_test(test_basename, testargs: List[str], output_dir: str,
no_extra_args=False, dryrun=False,
@@ -253,7 +258,8 @@ def run_full_test(test_basename, testargs: List[str], output_dir: str,
# Append arguments to write log to qtestlib XML file,
# and text to stdout.
if not no_extra_args:
- results_files.append(os.path.join(output_dir, test_basename + ".xml"))
+ results_files.append(
+ os.path.join(output_dir, unique_filename(test_basename)))
output_testargs.extend(["-o", results_files[0] + ",xml"])
output_testargs.extend(["-o", "-,txt"])
@@ -263,7 +269,8 @@ def run_full_test(test_basename, testargs: List[str], output_dir: str,
return (proc.returncode, results_files[0] if results_files else None)
-def rerun_failed_testcase(testargs: List[str], what_failed: WhatFailed,
+def rerun_failed_testcase(test_basename, testargs: List[str], output_dir: str,
+ what_failed: WhatFailed,
max_repeats, passes_needed,
dryrun=False, timeout=None) -> bool:
"""Run a specific function:tag of a test, until it passes enough times, or
@@ -276,13 +283,20 @@ def rerun_failed_testcase(testargs: List[str], what_failed: WhatFailed,
if what_failed.tag:
failed_arg += ":" + what_failed.tag
+
n_passes = 0
for i in range(max_repeats):
+ # For the individual testcase re-runs, we log to file since Coin needs
+ # to parse it. That is the reason we use unique filename every time.
+ output_args = [
+ "-o", os.path.join(output_dir, unique_filename(test_basename)) + ",xml",
+ "-o", "-,txt"]
L.info("Re-running testcase: %s", failed_arg)
if i < max_repeats - 1:
- proc = run_test(testargs + [failed_arg], timeout=timeout)
+ proc = run_test(testargs + output_args + [failed_arg],
+ timeout=timeout)
else: # last re-run
- proc = run_test(testargs + VERBOSE_ARGS + [failed_arg],
+ proc = run_test(testargs + output_args + VERBOSE_ARGS + [failed_arg],
timeout=timeout,
env={**os.environ, **VERBOSE_ENV})
if proc.returncode == 0:
@@ -356,8 +370,8 @@ def main():
for what_failed in failed_functions:
try:
- ret = rerun_failed_testcase(args.testargs, what_failed,
- args.max_repeats, args.passes_needed,
+ ret = rerun_failed_testcase(args.test_basename, args.testargs, args.log_dir,
+ what_failed, args.max_repeats, args.passes_needed,
dryrun=args.dry_run, timeout=args.timeout)
except Exception as e:
L.exception("The test executable CRASHed uncontrollably!"