diff --git a/Testing/SystemTests/scripts/InstallerTests.py b/Testing/SystemTests/scripts/InstallerTests.py index 93b406a63466aacd9804912f7808647737249d3c..d2f8391425005d864f6b3d1b5aa98dfeaae1dda1 100644 --- a/Testing/SystemTests/scripts/InstallerTests.py +++ b/Testing/SystemTests/scripts/InstallerTests.py @@ -32,6 +32,10 @@ parser.add_argument('-n', dest='doInstall', action='store_false', help='Run tests without installing Mantid (it must be already installed)') +parser.add_argument('-N', '--dry-run', + dest='dry_run', + action='store_true', + help='Do not run tests just print what would be run.') parser.add_argument('-o', dest='out2stdout', action='store_true', @@ -129,6 +133,8 @@ try: run_test_cmd += ' --exclude-in-pull-requests' if options.ignore_failed_imports: run_test_cmd += ' --ignore-failed-imports' + if options.dry_run: + run_test_cmd += ' --dry-run' if options.out2stdout: print("Executing command '{0}'".format(run_test_cmd)) p = subprocess.Popen(run_test_cmd, shell=True) # no PIPE: print on screen for debugging diff --git a/Testing/SystemTests/scripts/runSystemTests.py b/Testing/SystemTests/scripts/runSystemTests.py index 0088802874b55726e7a68074e87172c72769233e..21e5f6bb9f0aa6a1031d216c1edff2281d5394e0 100755 --- a/Testing/SystemTests/scripts/runSystemTests.py +++ b/Testing/SystemTests/scripts/runSystemTests.py @@ -14,6 +14,7 @@ import sys import time from multiprocessing import Process, Array, Manager, Value, Lock +from six import itervalues try: # If any tests happen to hit a PyQt4 import make sure item uses version 2 of the api # Remove this when everything is switched to qtpy @@ -121,6 +122,10 @@ def main(): dest="output_on_failure", action="store_true", help="Print full log for failed tests.") + parser.add_argument('-N', '--dry-run', + dest='dry_run', + action='store_true', + help='Do not run tests just print what would be run.') parser.add_argument("--showskipped", dest="showskipped", action="store_true", @@ -222,76 +227,79 @@ def main(): if file.startswith('TEST-systemtests-') and file.endswith('.xml'): os.remove(os.path.join(mtdconf.saveDir, file)) - # Multi-core processes -------------- - # An array to hold the processes - processes = [] - # A shared array to hold skipped and failed tests + status - results_array = Array('i', [0] * (3 * options.ncores)) - # A manager to create a shared dict to store names of skipped and failed tests - manager = Manager() - # A shared dict to store names of skipped and failed tests - status_dict = manager.dict() - # A shared dict to store the global list of tests - tests_dict = manager.dict() - # A shared array with 0s and 1s to keep track of completed tests - tests_lock = Array('i', [0] * number_of_test_modules) - # A shared value to count the number of remaining test modules - tests_left = Value('i', number_of_test_modules) - # A shared value to count the number of completed tests - tests_done = Value('i', 0) - # A shared dict to store which data files are required by each test module - required_files_dict = manager.dict() - for key in files_required_by_test_module.keys(): - required_files_dict[key] = files_required_by_test_module[key] - # A shared dict to store the locked status of each data file - locked_files_dict = manager.dict() - for key in data_file_lock_status.keys(): - locked_files_dict[key] = data_file_lock_status[key] - - # Store in reverse number of number of tests in each module into the shared dictionary - reverse_sorted_dict = [(k, test_counts[k]) - for k in sorted(test_counts, key=test_counts.get, reverse=True)] - counter = 0 - for key, value in reverse_sorted_dict: - tests_dict[str(counter)] = test_list[key] - counter += 1 - if not options.quiet: - print("Test module {} has {} tests:".format(key, value)) - for t in test_list[key]: - print(" - {}".format(t._fqtestname)) - print() - - # Define a lock - lock = Lock() - - # Prepare ncores processes - for ip in range(options.ncores): - processes.append( - Process(target=systemtesting.testThreadsLoop, - args=(mtdconf.testDir, mtdconf.saveDir, mtdconf.dataDir, options, tests_dict, - tests_lock, tests_left, results_array, status_dict, total_number_of_tests, - maximum_name_length, tests_done, ip, lock, required_files_dict, - locked_files_dict))) - # Start and join processes - try: - for p in processes: - p.start() - - for p in processes: - p.join() - except KeyboardInterrupt: - print("Killed via KeyboardInterrupt") - kill_children(processes) - except Exception as e: - print("Unexpected exception occured: {}".format(e)) - kill_children(processes) - - # Gather results - skipped_tests = sum(results_array[:options.ncores]) + (test_stats[2] - test_stats[0]) - failed_tests = sum(results_array[options.ncores:2 * options.ncores]) - total_tests = test_stats[2] - # Find minimum of status: if min == 0, then success is False - success = bool(min(results_array[2 * options.ncores:3 * options.ncores])) + if not options.dry_run: + # Multi-core processes -------------- + # An array to hold the processes + processes = [] + # A shared array to hold skipped and failed tests + status + results_array = Array('i', [0] * (3 * options.ncores)) + # A manager to create a shared dict to store names of skipped and failed tests + manager = Manager() + # A shared dict to store names of skipped and failed tests + status_dict = manager.dict() + # A shared dict to store the global list of tests + tests_dict = manager.dict() + # A shared array with 0s and 1s to keep track of completed tests + tests_lock = Array('i', [0] * number_of_test_modules) + # A shared value to count the number of remaining test modules + tests_left = Value('i', number_of_test_modules) + # A shared value to count the number of completed tests + tests_done = Value('i', 0) + # A shared dict to store which data files are required by each test module + required_files_dict = manager.dict() + for key in files_required_by_test_module.keys(): + required_files_dict[key] = files_required_by_test_module[key] + # A shared dict to store the locked status of each data file + locked_files_dict = manager.dict() + for key in data_file_lock_status.keys(): + locked_files_dict[key] = data_file_lock_status[key] + + # Store in reverse number of number of tests in each module into the shared dictionary + reverse_sorted_dict = [(k, test_counts[k]) + for k in sorted(test_counts, key=test_counts.get, reverse=True)] + counter = 0 + for key, value in reverse_sorted_dict: + tests_dict[str(counter)] = test_list[key] + counter += 1 + if not options.quiet: + print("Test module {} has {} tests:".format(key, value)) + for t in test_list[key]: + print(" - {}".format(t._fqtestname)) + print() + + # Define a lock + lock = Lock() + + # Prepare ncores processes + for ip in range(options.ncores): + processes.append( + Process(target=systemtesting.testThreadsLoop, + args=(mtdconf.testDir, mtdconf.saveDir, mtdconf.dataDir, options, tests_dict, + tests_lock, tests_left, results_array, status_dict, total_number_of_tests, + maximum_name_length, tests_done, ip, lock, required_files_dict, + locked_files_dict))) + # Start and join processes + try: + for p in processes: + p.start() + + for p in processes: + p.join() + except KeyboardInterrupt: + print("Killed via KeyboardInterrupt") + kill_children(processes) + except Exception as e: + print("Unexpected exception occured: {}".format(e)) + kill_children(processes) + + # Gather results + skipped_tests = sum(results_array[:options.ncores]) + (test_stats[2] - test_stats[0]) + failed_tests = sum(results_array[options.ncores:2 * options.ncores]) + total_tests = test_stats[2] + # Find minimum of status: if min == 0, then success is False + success = bool(min(results_array[2 * options.ncores:3 * options.ncores])) + else: + print("Dry run requested. Skipping execution") ######################################################################### # Cleanup @@ -305,10 +313,15 @@ def main(): total_runtime = time.strftime("%H:%M:%S", time.gmtime(end_time - start_time)) ######################################################################### - # Output summary to terminal (skip if this was a cleanup run) + # Output summary to terminal ######################################################################### - - if not options.clean: + if options.dry_run: + print() + print("Tests that would be executed:") + for suites in itervalues(test_list): + for suite in suites: + print(' ' + suite.name) + elif not options.clean: nwidth = 80 banner = "#" * nwidth print('\n' + banner)