From 919237958933d93b23f6cffb64e25a7469c948f5 Mon Sep 17 00:00:00 2001 From: Xylar Asay-Davis Date: Fri, 16 Apr 2021 11:06:24 +0200 Subject: [PATCH] Move run_*() functions into run module This makes more conceptual sense than having them in the suite, testcase and step modules because they all get called only when `compass run` gets called. --- compass/run.py | 136 +++++++++++++++++++++++++++++++++++++++++++- compass/step.py | 24 -------- compass/suite.py | 90 ----------------------------- compass/testcase.py | 22 ------- 4 files changed, 133 insertions(+), 139 deletions(-) diff --git a/compass/run.py b/compass/run.py index c5a8116b2b..237e6702b9 100644 --- a/compass/run.py +++ b/compass/run.py @@ -1,10 +1,140 @@ import argparse import sys import os +import pickle +import configparser +import time +import numpy -from compass.suite import run_suite -from compass.testcase import run_test_case -from compass.step import run_step +from mpas_tools.logging import LoggingContext + + +def run_suite(suite_name): + """ + Run the given test suite + + Parameters + ---------- + suite_name : str + The name of the test suite + """ + with open('{}.pickle'.format(suite_name), 'rb') as handle: + test_suite = pickle.load(handle) + + # start logging to stdout/stderr + with LoggingContext(suite_name) as logger: + + os.environ['PYTHONUNBUFFERED'] = '1' + + try: + os.makedirs('case_outputs') + except OSError: + pass + + failures = 0 + cwd = os.getcwd() + suite_start = time.time() + test_times = dict() + success = dict() + for test_name in test_suite['test_cases']: + test_case = test_suite['test_cases'][test_name] + + logger.info('{}'.format(test_name)) + + test_name = test_case.path.replace('/', '_') + log_filename = '{}/case_outputs/{}.log'.format(cwd, test_name) + with LoggingContext(test_name, log_filename=log_filename) as \ + test_logger: + test_case.logger = test_logger + test_case.log_filename = log_filename + test_case.new_step_log_file = False + + os.chdir(test_case.work_dir) + + config = configparser.ConfigParser( + interpolation=configparser.ExtendedInterpolation()) + config.read(test_case.config_filename) + test_case.config = config + + test_start = time.time() + try: + test_case.run() + logger.info(' PASS') + success[test_name] = 'PASS' + except BaseException: + test_logger.exception('Exception raised') + logger.error( + ' FAIL see: case_outputs/{}.log'.format(test_name)) + success[test_name] = 'FAIL' + failures += 1 + test_times[test_name] = time.time() - test_start + + suite_time = time.time() - suite_start + + os.chdir(cwd) + + logger.info('Test Runtimes:') + for test_name, test_time in test_times.items(): + mins = int(numpy.floor(test_time / 60.0)) + secs = int(numpy.ceil(test_time - mins * 60)) + logger.info('{:02d}:{:02d} {} {}'.format( + mins, secs, success[test_name], test_name)) + mins = int(numpy.floor(suite_time / 60.0)) + secs = int(numpy.ceil(suite_time - mins * 60)) + logger.info('Total runtime {:02d}:{:02d}'.format(mins, secs)) + + if failures == 0: + logger.info('PASS: All passed successfully!') + else: + if failures == 1: + message = '1 test' + else: + message = '{} tests'.format(failures) + logger.error('FAIL: {} failed, see above.'.format(message)) + sys.exit(1) + + +def run_test_case(): + """ + Used by the framework to run a test case when ``compass run`` gets called + in the test case's work directory + """ + with open('test_case.pickle', 'rb') as handle: + test_case = pickle.load(handle) + + config = configparser.ConfigParser( + interpolation=configparser.ExtendedInterpolation()) + config.read(test_case.config_filename) + test_case.config = config + + # start logging to stdout/stderr + test_name = test_case.path.replace('/', '_') + test_case.new_step_log_file = True + with LoggingContext(name=test_name) as logger: + test_case.logger = logger + test_case.run() + + +def run_step(): + """ + Used by the framework to run a step when ``compass run`` gets called in the + step's work directory + """ + with open('step.pickle', 'rb') as handle: + test_case, step = pickle.load(handle) + test_case.steps_to_run = [step.name] + test_case.new_step_log_file = False + + config = configparser.ConfigParser( + interpolation=configparser.ExtendedInterpolation()) + config.read(step.config_filename) + test_case.config = config + + # start logging to stdout/stderr + test_name = step.path.replace('/', '_') + with LoggingContext(name=test_name) as logger: + test_case.logger = logger + test_case.run() def main(): diff --git a/compass/step.py b/compass/step.py index beae0ef28d..3de6562f45 100644 --- a/compass/step.py +++ b/compass/step.py @@ -1,9 +1,7 @@ import os from lxml import etree -import pickle import configparser -from mpas_tools.logging import LoggingContext from compass.io import download, symlink import compass.namelist import compass.streams @@ -533,25 +531,3 @@ def _generate_streams(self): defaults.remove(default) compass.streams.write(defaults_tree, out_filename) - - -def run_step(): - """ - Used by the framework to run a step when ``compass run`` gets called in the - step's work directory - """ - with open('step.pickle', 'rb') as handle: - test_case, step = pickle.load(handle) - test_case.steps_to_run = [step.name] - test_case.new_step_log_file = False - - config = configparser.ConfigParser( - interpolation=configparser.ExtendedInterpolation()) - config.read(step.config_filename) - test_case.config = config - - # start logging to stdout/stderr - test_name = step.path.replace('/', '_') - with LoggingContext(name=test_name) as logger: - test_case.logger = logger - test_case.run() diff --git a/compass/suite.py b/compass/suite.py index 96f5e7ba7e..7126484a05 100644 --- a/compass/suite.py +++ b/compass/suite.py @@ -3,11 +3,6 @@ import os from importlib import resources import pickle -import configparser -import time -import numpy - -from mpas_tools.logging import LoggingContext from compass.setup import setup_cases from compass.io import symlink @@ -131,91 +126,6 @@ def clean_suite(mpas_core, suite_name, work_dir=None): pass -def run_suite(suite_name): - """ - Run the given test suite - - Parameters - ---------- - suite_name : str - The name of the test suite - """ - with open('{}.pickle'.format(suite_name), 'rb') as handle: - test_suite = pickle.load(handle) - - # start logging to stdout/stderr - with LoggingContext(suite_name) as logger: - - os.environ['PYTHONUNBUFFERED'] = '1' - - try: - os.makedirs('case_outputs') - except OSError: - pass - - failures = 0 - cwd = os.getcwd() - suite_start = time.time() - test_times = dict() - success = dict() - for test_name in test_suite['test_cases']: - test_case = test_suite['test_cases'][test_name] - - logger.info('{}'.format(test_name)) - - test_name = test_case.path.replace('/', '_') - log_filename = '{}/case_outputs/{}.log'.format(cwd, test_name) - with LoggingContext(test_name, log_filename=log_filename) as \ - test_logger: - test_case.logger = test_logger - test_case.log_filename = log_filename - test_case.new_step_log_file = False - - os.chdir(test_case.work_dir) - - config = configparser.ConfigParser( - interpolation=configparser.ExtendedInterpolation()) - config.read(test_case.config_filename) - test_case.config = config - - test_start = time.time() - try: - test_case.run() - logger.info(' PASS') - success[test_name] = 'PASS' - except BaseException: - test_logger.exception('Exception raised') - logger.error( - ' FAIL see: case_outputs/{}.log'.format(test_name)) - success[test_name] = 'FAIL' - failures += 1 - test_times[test_name] = time.time() - test_start - - suite_time = time.time() - suite_start - - os.chdir(cwd) - - logger.info('Test Runtimes:') - for test_name, test_time in test_times.items(): - mins = int(numpy.floor(test_time / 60.0)) - secs = int(numpy.ceil(test_time - mins * 60)) - logger.info('{:02d}:{:02d} {} {}'.format( - mins, secs, success[test_name], test_name)) - mins = int(numpy.floor(suite_time / 60.0)) - secs = int(numpy.ceil(suite_time - mins * 60)) - logger.info('Total runtime {:02d}:{:02d}'.format(mins, secs)) - - if failures == 0: - logger.info('PASS: All passed successfully!') - else: - if failures == 1: - message = '1 test' - else: - message = '{} tests'.format(failures) - logger.error('FAIL: {} failed, see above.'.format(message)) - sys.exit(1) - - def main(): parser = argparse.ArgumentParser( description='Set up a regression test suite', prog='compass suite') diff --git a/compass/testcase.py b/compass/testcase.py index 8491059c4a..4c8896172f 100644 --- a/compass/testcase.py +++ b/compass/testcase.py @@ -1,5 +1,4 @@ import os -import pickle import configparser from mpas_tools.logging import LoggingContext @@ -234,24 +233,3 @@ def _run_step(self, step, new_log_file): 'output file(s) missing in step {} of {}/{}/{}: {}'.format( step.name, step.mpas_core.name, step.test_group.name, step.test_case.subdir, missing_files)) - - -def run_test_case(): - """ - Used by the framework to run a test case when ``compass run`` gets called - in the test case's work directory - """ - with open('test_case.pickle', 'rb') as handle: - test_case = pickle.load(handle) - - config = configparser.ConfigParser( - interpolation=configparser.ExtendedInterpolation()) - config.read(test_case.config_filename) - test_case.config = config - - # start logging to stdout/stderr - test_name = test_case.path.replace('/', '_') - test_case.new_step_log_file = True - with LoggingContext(name=test_name) as logger: - test_case.logger = logger - test_case.run()