Skip to content

Commit

Permalink
[tests] color test results and sort alphabetically
Browse files Browse the repository at this point in the history
Summary:
Backport core's PR10159 and PR10222

Depends on D996

Test Plan:
  ./test/functional/test_runner.py

Reviewers: #bitcoin_abc, schancel

Reviewed By: #bitcoin_abc, schancel

Subscribers: teamcity

Differential Revision: https://reviews.bitcoinabc.org/D998
  • Loading branch information
jnewbery authored and deadalnix committed Jan 22, 2018
1 parent 5fcce3f commit dbe08ab
Showing 1 changed file with 77 additions and 30 deletions.
107 changes: 77 additions & 30 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,26 @@
import re
import logging

BOLD = ("", "")
RED = ("", "")
GREEN = ("", "")
# Formatting. Default colors to empty strings.
BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
try:
# Make sure python thinks it can write unicode to its stdout
"\u2713".encode("utf_8").decode(sys.stdout.encoding)
TICK = "✓ "
CROSS = "✖ "
CIRCLE = "○ "
except UnicodeDecodeError:
TICK = "P "
CROSS = "x "
CIRCLE = "o "

if os.name == 'posix':
# primitive formatting on supported
# terminal via ANSI escape sequences:
BOLD = ('\033[0m', '\033[1m')
RED = ("\033[0m", "\033[31m")
GREEN = ("\033[0m", "\033[32m")
BLUE = ('\033[0m', '\033[0;34m')
RED = ('\033[0m', '\033[0;31m')
GREY = ('\033[0m', '\033[1;30m')

TEST_EXIT_PASSED = 0
TEST_EXIT_SKIPPED = 77
Expand Down Expand Up @@ -266,48 +277,63 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal
subprocess.check_output([tests_dir + 'create_cache.py'] + flags)

# Run Tests
all_passed = True
time_sum = 0
time0 = time.time()

job_queue = TestHandler(jobs, tests_dir, test_list, flags)
time0 = time.time()
test_results = []

max_len_name = len(max(test_list, key=len))
results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % (
"TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0]

for _ in range(len(test_list)):
(name, stdout, stderr, status, duration) = job_queue.get_next()
all_passed = all_passed and status != "Failed"
time_sum += duration

if status == "Passed":
logging.debug("\n%s%s%s passed, Duration: %s s" %
(BOLD[1], name, BOLD[0], duration))
elif status == "Skipped":
logging.debug("\n%s%s%s skipped" % (BOLD[1], name, BOLD[0]))
test_result, stdout, stderr = job_queue.get_next()
test_results.append(test_result)

if test_result.status == "Passed":
logging.debug("\n%s%s%s passed, Duration: %s s" % (
BOLD[1], test_result.name, BOLD[0], test_result.time))
elif test_result.status == "Skipped":
logging.debug("\n%s%s%s skipped" %
(BOLD[1], test_result.name, BOLD[0]))
else:
print("\n%s%s%s failed, Duration: %s s\n" %
(BOLD[1], name, BOLD[0], duration))
(BOLD[1], test_result.name, BOLD[0], test_result.time))
print(BOLD[1] + 'stdout:\n' + BOLD[0] + stdout + '\n')
print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n')

results += "%s | %s | %s s\n" % (name.ljust(max_len_name),
status.ljust(7), duration)

results += BOLD[1] + "\n{name} | {passed} | {duration}s (accumulated)".format(
name="ALL".ljust(max_len_name), passed=str(all_passed).ljust(6), duration=time_sum) + BOLD[0]
print(results)
print("\nRuntime: {} s".format(int(time.time() - time0)))
print_results(test_results, max_len_name, (int(time.time() - time0)))

if coverage:
coverage.report_rpc_coverage()

logging.debug("Cleaning up coverage data")
coverage.cleanup()

all_passed = all(
map(lambda test_result: test_result.status == "Passed", test_results))

sys.exit(not all_passed)


def print_results(test_results, max_len_name, runtime):
results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % (
"TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0]

test_results.sort(key=lambda result: result.name.lower())
all_passed = True
time_sum = 0

for test_result in test_results:
all_passed = all_passed and test_result.status != "Failed"
time_sum += test_result.time
test_result.padding = max_len_name
results += str(test_result)

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


class TestHandler:

"""
Expand Down Expand Up @@ -370,11 +396,32 @@ def get_next(self):
status = "Failed"
self.num_running -= 1
self.jobs.remove(j)
return name, stdout, stderr, status, int(
time.time() - time0)

return TestResult(name, status, int(time.time() - time0)), stdout, stderr
print('.', end='', flush=True)


class TestResult():
def __init__(self, name, status, time):
self.name = name
self.status = status
self.time = time
self.padding = 0

def __repr__(self):
if self.status == "Passed":
color = BLUE
glyph = TICK
elif self.status == "Failed":
color = RED
glyph = CROSS
elif self.status == "Skipped":
color = GREY
glyph = CIRCLE

return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0]


def check_script_list(src_dir):
"""Check scripts directory.
Expand Down

0 comments on commit dbe08ab

Please sign in to comment.