Repository: bitcoin/bitcoin
File: test/functional/test_runner.py (Python)

Code before:
    print(results)

class TestHandler:
    """
    Trigger the test scripts passed in via the list.
    """

    def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, use_term_control):
        assert num_tests_parallel >= 1
        self.num_jobs = num_tests_parallel
        self.tests_dir = tests_dir
        self.tmpdir = tmpdir
        self.test_list = test_list
        self.flags = flags
        self.jobs = []
        self.use_term_control = use_term_control

    def done(self):
        return not (self.jobs or self.test_list)

    def get_next(self):
        while len(self.jobs) < self.num_jobs and self.test_list:
            # Add tests
            test = self.test_list.pop(0)
            portseed = len(self.test_list)
            portseed_arg = ["--portseed={}".format(portseed)]
            log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16)
            log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16)
            test_argv = test.split()
            testdir = "{}/{}_{}".format(self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed)
            tmpdir_arg = ["--tmpdir={}".format(testdir)]
            self.jobs.append((test,
                              time.time(),
                              subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg,
                                               text=True,
                                               stdout=log_stdout,
                                               stderr=log_stderr),
                              testdir,
                              log_stdout,
                              log_stderr))
        if not self.jobs:
            raise IndexError('pop from empty list')

        # Print remaining running jobs when all jobs have been started.
        if not self.test_list:
            print("Remaining jobs: [{}]".format(", ".join(j[0] for j in self.jobs)))

        dot_count = 0
        while True:
            # Return all procs that have finished, if any. Otherwise sleep until there is one.
            time.sleep(.5)

Review comment (bug):
Nit: Having had only few tests failed also display `ALL,Failed`, which in the first glance gives the impression that all of them failed. In cases like this, displaying `ALL, Few failed` would be more explicit.

Code after:

    for test_result in test_results:
        all_passed = all_passed and test_result.was_successful
        time_sum += test_result.time
        test_result.padding = max_len_name
        results += str(test_result)

    status = TICK + "Passed" if all_passed else CROSS + "Failed"
    if not all_passed:
        results += RED[1]
    results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(9), time_sum) + BOLD[0]
    if not all_passed:
        results += RED[0]
    results += "Runtime: %s s\n" % (runtime)
    print(results)


def write_results(test_results, filepath, total_runtime):
    with open(filepath, mode="w", encoding="utf8") as results_file:
        results_writer = csv.writer(results_file)
        results_writer.writerow(['test', 'status', 'duration(seconds)'])
        all_passed = True
        for test_result in test_results:
            all_passed = all_passed and test_result.was_successful
            results_writer.writerow([test_result.name, test_result.status, str(test_result.time)])
        results_writer.writerow(['ALL', ("Passed" if all_passed else "Failed"), str(total_runtime)])

class TestHandler:
    """
    Trigger the test scripts passed in via the list.
    """

    def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, use_term_control):
        assert num_tests_parallel >= 1
        self.num_jobs = num_tests_parallel
        self.tests_dir = tests_dir
        self.tmpdir = tmpdir
        self.test_list = test_list
        self.flags = flags
        self.jobs = []
        self.use_term_control = use_term_control

    def done(self):
        return not (self.jobs or self.test_list)

    def get_next(self):
        while len(self.jobs) < self.num_jobs and self.test_list:
            # Add tests
            test = self.test_list.pop(0)
            portseed = len(self.test_list)
            portseed_arg = ["--portseed={}".format(portseed)]