def __init__(self, chief): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._results = TestExecutionResults() self.port = None self._chief = chief self.profiles = {}
def __init__(self, project): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._pid_to_kill = None self._results = TestExecutionResults() self.port = None self._project = project self.profiles = {}
def __init__(self, chief): self._output_dir = None self._process = None self._server = None self._server_thread = None self._results = TestExecutionResults() self.port = None self._chief = chief self.profiles = {}
def __init__(self, chief): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._pid_to_kill = None self._results = TestExecutionResults() self.port = None self._chief = chief self.profiles = {}
def __init__(self, project): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._pid_to_kill = None self._results = TestExecutionResults() self.port = None self._project = project self.profiles = {} self._pause_longname = None self._pause_testname = None
class TestRunner(object): def __init__(self, chief): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._results = TestExecutionResults() self.port = None self._chief = chief self.profiles = {} def enable(self, result_handler): self._start_listener_server(result_handler) self._create_temporary_directory() def _create_temporary_directory(self): self._output_dir = tempfile.mkdtemp(".d", "RIDE") atexit.register(self._remove_temporary_directory) # this plugin creates a temporary directory which _should_ # get reaped at exit. Sometimes things happen which might # cause it to not get deleted. Maybe this would be a good # place to check for temporary directories that match the # signature and delete them if they are more than a few # days old... def _remove_temporary_directory(self): with ATEXIT_LOCK: if os.path.exists(self._output_dir): shutil.rmtree(self._output_dir) def add_profile(self, name, item): self.profiles[name] = item def get_profile(self, name): return self.profiles[name] def get_profile_names(self): return sorted(self.profiles.keys()) def _start_listener_server(self, result_handler): def handle(*args): self._result_handler(*args) result_handler(*args) self._server = RideListenerServer(RideListenerHandler, handle) self._server_thread = threading.Thread(target=self._server.serve_forever) self._server_thread.setDaemon(True) self._server_thread.start() self.port = self._server.server_address[1] def _result_handler(self, event, *args): if event == 'pid': self._pid_to_kill = int(args[0]) if event == 'port' and self._process: self._process.set_port(args[0]) self._send_pause_on_failure_information() if event == 'start_test': longname = args[1]['longname'] testname = args[0] self._results.set_running(self._get_test_controller(longname, testname)) if event == 'end_test': longname = args[1]['longname'] testname = args[0] if args[1]['status'] == 'PASS': self._results.set_passed(self._get_test_controller(longname, testname)) else: self._results.set_failed(self._get_test_controller(longname, testname)) def _get_test_controller(self, longname, testname = None): ret = self._chief.find_controller_by_longname(longname, testname) return ret def clear_server(self): self._server = None def shutdown_server(self): if self._server: self._server.shutdown() def test_execution_started(self): self._results.test_execution_started() def kill_process(self): if self._process: self._process.kill(force=True) def set_pause_on_failure(self, pause): self._pause_on_failure = pause self._send_pause_on_failure_information() def _send_pause_on_failure_information(self): if self._process: self._process.pause_on_failure(self._pause_on_failure) def send_stop_signal(self): if self._process: self._process.kill(killer_pid=self._pid_to_kill) def send_pause_signal(self): if self._process: self._process.pause() def send_continue_signal(self): if self._process: self._process.resume() def send_step_next_signal(self): if self._process: self._process.step_next() def send_step_over_signal(self): if self._process: self._process.step_over() def run_command(self, command, cwd): self._pid_to_kill = None self._process = Process(cwd) self._process.run_command(command) def get_command(self, profile, pythonpath, monitor_width, test_names): '''Return the command (as a list) used to run the test''' command = profile.get_command_prefix()[:] argfile = os.path.join(self._output_dir, "argfile.txt") command.extend(["--argumentfile", argfile]) command.extend(["--listener", self._get_listener_to_cmd()]) command.append(self._get_suite_source_for_command()) self._write_argfile(argfile, self._create_standard_args(command, profile, pythonpath, monitor_width, test_names)) return command def get_message_log_level(self, command): min_log_level_number = LEVELS['INFO'] if '-L' in command: switch = '-L' elif '--loglevel' in command: switch = '--loglevel' else: return min_log_level_number i = command.index(switch) if len(command) == i: return level = command[i+1].upper().split(':')[0] return LEVELS.get(level, min_log_level_number) def _get_listener_to_cmd(self): path = os.path.abspath(TestRunnerAgent.__file__) if path[-1] in ['c', 'o']: path = path[:-1] return '%s:%s' % (path, self.port) def _get_suite_source_for_command(self): cur = os.path.abspath(os.path.curdir) source = os.path.abspath(self._chief.suite.source) if not utils.is_same_drive(cur, source): return source return os.path.abspath(self._chief.suite.source) def _create_standard_args(self, command, profile, pythonpath, monitor_width, test_names): standard_args = [] standard_args.extend(profile.get_custom_args()) self._add_tmp_outputdir_if_not_given_by_user(command, standard_args) self._add_pythonpath_if_in_settings_and_not_given_by_user(command, standard_args, pythonpath) standard_args.extend(["--monitorcolors", "off"]) standard_args.extend(["--monitorwidth", monitor_width]) for tc in test_names: standard_args += ['--test', tc] return standard_args def _add_tmp_outputdir_if_not_given_by_user(self, command, standard_args): if "--outputdir" not in command and "-d" not in command: standard_args.extend(["--outputdir", self._output_dir]) def _add_pythonpath_if_in_settings_and_not_given_by_user(self, command, standard_args, pythonpath): if '--pythonpath' in command: return if '-P' in command: return if not pythonpath: return standard_args.extend(['--pythonpath', ':'.join(pythonpath)]) def _write_argfile(self, argfile, args): f = codecs.open(argfile, "w", "utf-8") f.write("\n".join(args)) f.close() def get_output_and_errors(self): return self._process.get_output(), self._process.get_errors() def is_running(self): return self._process and self._process.is_alive() def command_ended(self): self._process = None
class TestRunner(object): def __init__(self, project): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._pid_to_kill = None self._results = TestExecutionResults() self.port = None self._project = project self.profiles = {} self._pause_longname = None self._pause_testname = None def enable(self, result_handler): self._start_listener_server(result_handler) self._create_temporary_directory() def _create_temporary_directory(self): self._output_dir = tempfile.mkdtemp(".d", "RIDE") atexit.register(self._remove_temporary_directory) # this plugin creates a temporary directory which _should_ # get reaped at exit. Sometimes things happen which might # cause it to not get deleted. Maybe this would be a good # place to check for temporary directories that match the # signature and delete them if they are more than a few # days old... def _remove_temporary_directory(self): with ATEXIT_LOCK: if os.path.exists(self._output_dir): shutil.rmtree(self._output_dir) def add_profile(self, name, item): self.profiles[name] = item def get_profile(self, name): return self.profiles[name] def get_profile_names(self): return sorted(self.profiles.keys()) def _start_listener_server(self, result_handler): def handle(*args): self._result_handler(*args) result_handler(*args) self._server = RideListenerServer(RideListenerHandler, handle) self._server_thread = threading.Thread( target=self._server.serve_forever) self._server_thread.setDaemon(True) self._server_thread.start() self.port = self._server.server_address[1] def _result_handler(self, event, *args): # print("DEBUG: testrunner event %s" % event) if event == 'pid': self._pid_to_kill = int(args[0]) if event == 'port' and self._process: self._process.set_port(args[0]) if event == 'start_test': longname = args[1]['longname'] testname = args[0] self._results.set_running(self._get_test_controller(longname, testname)) self._pause_longname = longname self._pause_testname = testname if event == 'continue': # print("DEBUG: testrunner resume %s" % self._results.RUNNING) self._results.set_running(self._get_test_controller( self._pause_longname, self._pause_testname)) if event == 'paused': # print("DEBUG: testrunner pause %s" % self._results.PAUSED) self._results.set_paused(self._get_test_controller( self._pause_longname, self._pause_testname)) if event == 'end_test': longname = args[1]['longname'] testname = args[0] if args[1]['status'] == 'PASS': self._results.set_passed(self._get_test_controller(longname, testname)) else: self._results.set_failed(self._get_test_controller(longname, testname)) def _get_test_controller(self, longname, testname=None): ret = self._project.find_controller_by_longname(longname, testname) return ret def clear_server(self): self._server = None def shutdown_server(self): if self._server: self._server.shutdown() def test_execution_started(self): self._results.test_execution_started() def kill_process(self): if self._process: self._process.kill(force=True) def set_pause_on_failure(self, pause): self._pause_on_failure = pause self._send_pause_on_failure_information() def _send_pause_on_failure_information(self): if self._process: self._process.pause_on_failure(self._pause_on_failure) def send_stop_signal(self): if self._process: self._process.kill(killer_pid=self._pid_to_kill) def send_pause_signal(self): if self._process: self._process.pause() def send_continue_signal(self): if self._process: self._process.resume() def send_step_next_signal(self): if self._process: self._process.step_next() def send_step_over_signal(self): if self._process: self._process.step_over() def run_command(self, command, cwd): self._pid_to_kill = None if IS_WINDOWS: self._process = Process(cwd) # .encode(encoding.SYSTEM_ENCODING)) else: self._process = Process(cwd.encode(encoding.OUTPUT_ENCODING)) # print("DEBUG: run_command command: %s\nCWD: %s\n" % (command, cwd)) self._process.run_command(command) def get_command(self, profile, pythonpath, console_width, names_to_run): """Return the command (as a list) used to run the test""" command = profile.get_command_prefix()[:] argfile = os.path.join(self._output_dir, "argfile.txt") command.extend(["--argumentfile", argfile]) command.extend(["--listener", self._get_listener_to_cmd()]) command.append(self._get_suite_source_for_command()) self._write_argfile(argfile, self._create_standard_args( command, profile, pythonpath, console_width, names_to_run)) return command @staticmethod def get_message_log_level(command): min_log_level_number = LOG_LEVELS['INFO'] if '-L' in command: switch = '-L' elif '--loglevel' in command: switch = '--loglevel' else: return min_log_level_number i = command.index(switch) if len(command) == i: return level = command[i+1].upper().split(':')[0] return LOG_LEVELS.get(level, min_log_level_number) def _get_listener_to_cmd(self): path = os.path.abspath(TestRunnerAgent.__file__) if path[-1] in ['c', 'o']: path = path[:-1] return '%s:%s:%s' % (path, self.port, self._pause_on_failure) def _get_suite_source_for_command(self): cur = os.path.abspath(os.path.curdir) source = os.path.abspath(self._project.suite.source) if not utils.is_same_drive(cur, source): return source return os.path.abspath(self._project.suite.source) def _create_standard_args( self, command, profile, pythonpath, console_width, names_to_run): standard_args = [] standard_args.extend(profile.get_custom_args()) self._add_tmp_outputdir_if_not_given_by_user(command, standard_args) self._add_pythonpath_if_in_settings_and_not_given_by_user( command, standard_args, pythonpath) # Have to use short options, because of long option was changed in # RF 2.8 -> 2.9, and we don't necessarily know the installed version. standard_args.extend(["-C", "off"]) # --consolecolor standard_args.extend(["-W", console_width]) # --consolewidth for suite, test in names_to_run: standard_args += ['--suite', suite, '--test', test] return standard_args def _add_tmp_outputdir_if_not_given_by_user(self, command, standard_args): if "--outputdir" not in command and "-d" not in command: standard_args.extend(["--outputdir", self._output_dir]) @staticmethod def _add_pythonpath_if_in_settings_and_not_given_by_user( command, standard_args, pythonpath): if '--pythonpath' in command: return if '-P' in command: return if not pythonpath: return standard_args.extend(['--pythonpath', ':'.join(pythonpath)]) @staticmethod def _write_argfile(argfile, args): if PY2: f = codecs.open(argfile, "wb") for item in args: if is_unicode(item): enc_arg = item.encode(encoding.OUTPUT_ENCODING) else: enc_arg = item f.write(enc_arg+"\n") else: f = codecs.open(argfile, "w", "utf-8") f.write("\n".join(args)) f.close() def get_output_and_errors(self, profile): stdout, stderr, returncode = self._process.get_output(), \ self._process.get_errors(), self._process.get_returncode() error, log_message = profile.format_error(stderr, returncode) return stdout, error, log_message def is_running(self): return self._process and self._process.is_alive() def command_ended(self): self._process = None
class TestRunner(object): def __init__(self, project): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._pid_to_kill = None self._results = TestExecutionResults() self.port = None self._project = project self.profiles = {} self._pause_longname = None self._pause_testname = None def enable(self, result_handler): self._start_listener_server(result_handler) self._create_temporary_directory() def _create_temporary_directory(self): self._output_dir = tempfile.mkdtemp(".d", "RIDE") atexit.register(self._remove_temporary_directory) # this plugin creates a temporary directory which _should_ # get reaped at exit. Sometimes things happen which might # cause it to not get deleted. Maybe this would be a good # place to check for temporary directories that match the # signature and delete them if they are more than a few # days old... def _remove_temporary_directory(self): with ATEXIT_LOCK: if os.path.exists(self._output_dir): shutil.rmtree(self._output_dir) def add_profile(self, name, item): self.profiles[name] = item def get_profile(self, name): return self.profiles[name] def get_profile_names(self): return sorted(self.profiles.keys()) def _start_listener_server(self, result_handler): def handle(*args): self._result_handler(*args) result_handler(*args) self._server = RideListenerServer(RideListenerHandler, handle) self._server_thread = threading.Thread( target=self._server.serve_forever) self._server_thread.setDaemon(True) self._server_thread.start() self.port = self._server.server_address[1] def _result_handler(self, event, *args): # print("DEBUG: testrunner event %s" % event) if event == 'pid': self._pid_to_kill = int(args[0]) if event == 'port' and self._process: self._process.set_port(args[0]) if event == 'start_test': longname = args[1]['longname'] testname = args[0] self._results.set_running(self._get_test_controller(longname, testname)) self._pause_longname = longname self._pause_testname = testname if event == 'continue': # print("DEBUG: testrunner resume %s" % self._results.RUNNING) self._results.set_running(self._get_test_controller( self._pause_longname, self._pause_testname)) if event == 'paused': # print("DEBUG: testrunner pause %s" % self._results.PAUSED) self._results.set_paused(self._get_test_controller( self._pause_longname, self._pause_testname)) if event == 'end_test': longname = args[1]['longname'] testname = args[0] if args[1]['status'] == 'PASS': self._results.set_passed(self._get_test_controller(longname, testname)) else: self._results.set_failed(self._get_test_controller(longname, testname)) def _get_test_controller(self, longname, testname=None): ret = self._project.find_controller_by_longname(longname, testname) return ret def clear_server(self): self._server = None def shutdown_server(self): if self._server: self._server.shutdown() def test_execution_started(self): self._results.test_execution_started() def kill_process(self): if self._process: self._process.kill(force=True) def set_pause_on_failure(self, pause): self._pause_on_failure = pause self._send_pause_on_failure_information() def _send_pause_on_failure_information(self): if self._process: self._process.pause_on_failure(self._pause_on_failure) def send_stop_signal(self): if self._process: self._process.kill(killer_pid=self._pid_to_kill) def send_pause_signal(self): if self._process: self._process.pause() def send_continue_signal(self): if self._process: self._process.resume() def send_step_next_signal(self): if self._process: self._process.step_next() def send_step_over_signal(self): if self._process: self._process.step_over() def run_command(self, command, cwd): self._pid_to_kill = None self._process = Process(cwd) # print("DEBUG: run_command command: %s\nCWD: %s\n" % (command, cwd)) self._process.run_command(command) def get_command(self, profile, pythonpath, console_width, names_to_run): """Return the command (as a list) used to run the test""" command = profile.get_command_prefix()[:] argfile = os.path.join(self._output_dir, "argfile.txt") command.extend(["--argumentfile", argfile]) command.extend(["--listener", self._get_listener_to_cmd()]) command.append(self._get_suite_source_for_command()) self._write_argfile(argfile, self._create_standard_args( command, profile, pythonpath, console_width, names_to_run)) return command @staticmethod def get_message_log_level(command): min_log_level_number = LOG_LEVELS['INFO'] if '-L' in command: switch = '-L' elif '--loglevel' in command: switch = '--loglevel' else: return min_log_level_number i = command.index(switch) if len(command) == i: return level = command[i+1].upper().split(':')[0] return LOG_LEVELS.get(level, min_log_level_number) def _get_listener_to_cmd(self): path = os.path.abspath(TestRunnerAgent.__file__) if path[-1] in ['c', 'o']: path = path[:-1] return '%s:%s:%s' % (path, self.port, self._pause_on_failure) def _get_suite_source_for_command(self): cur = os.path.abspath(os.path.curdir) source = os.path.abspath(self._project.suite.source) if not utils.is_same_drive(cur, source): return source return os.path.abspath(self._project.suite.source) def _create_standard_args( self, command, profile, pythonpath, console_width, names_to_run): standard_args = [] standard_args.extend(profile.get_custom_args()) self._add_tmp_outputdir_if_not_given_by_user(command, standard_args) self._add_pythonpath_if_in_settings_and_not_given_by_user( command, standard_args, pythonpath) # Have to use short options, because of long option was changed in # RF 2.8 -> 2.9, and we don't necessarily know the installed version. standard_args.extend(["-C", "off"]) # --consolecolor standard_args.extend(["-W", console_width]) # --consolewidth for suite, test in names_to_run: standard_args += ['--suite', suite, '--test', test] return standard_args def _add_tmp_outputdir_if_not_given_by_user(self, command, standard_args): if "--outputdir" not in command and "-d" not in command: standard_args.extend(["--outputdir", self._output_dir]) @staticmethod def _add_pythonpath_if_in_settings_and_not_given_by_user( command, standard_args, pythonpath): if '--pythonpath' in command: return if '-P' in command: return if not pythonpath: return standard_args.extend(['--pythonpath', ':'.join(pythonpath)]) @staticmethod def _write_argfile(argfile, args): m_args = list() f = codecs.open(argfile, "wb") # , "utf-8") if PY2: # if IS_WINDOWS: # m_args = [unicode(item,"utf-8") for item in args] # else: # DEBUG # m_args = args for item in args: if is_unicode(item): m_args.append(item.encode("utf-8")) # .decode("utf-8")) else: m_args.append(bytes(item)) # DEBUG m_args = [item.decode("utf-8") for item in args] # print("DEBUG: write_args: %s\n" % m_args) else: m_args = [str(x) for x in args] # .encode("utf-8","surrogate") # print("DEBUG: write_args: %s\n" % m_args) # data = r"\n".join(m_args) if PY2: data = b"\n".join(m_args) f.write(bytes(data)) # DEBUG .decode("utf-8") .encode("utf-8") else: data = "\n".join(m_args) f.write(bytes(data.encode("utf-8", "surrogate"))) f.close() def get_output_and_errors(self, profile): stdout, stderr, returncode = self._process.get_output(), \ self._process.get_errors(), self._process.get_returncode() error, log_message = profile.format_error(stderr, returncode) return stdout, error, log_message def is_running(self): return self._process and self._process.is_alive() def command_ended(self): self._process = None
class TestRunner(object): def __init__(self, chief): self._output_dir = None self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._results = TestExecutionResults() self.port = None self._chief = chief self.profiles = {} def enable(self, result_handler): self._start_listener_server(result_handler) self._create_temporary_directory() def _create_temporary_directory(self): self._output_dir = tempfile.mkdtemp(".d", "RIDE") atexit.register(self._remove_temporary_directory) # this plugin creates a temporary directory which _should_ # get reaped at exit. Sometimes things happen which might # cause it to not get deleted. Maybe this would be a good # place to check for temporary directories that match the # signature and delete them if they are more than a few # days old... def _remove_temporary_directory(self): with ATEXIT_LOCK: if os.path.exists(self._output_dir): shutil.rmtree(self._output_dir) def add_profile(self, name, item): self.profiles[name] = item def get_profile(self, name): return self.profiles[name] def get_profile_names(self): return sorted(self.profiles.keys()) def _start_listener_server(self, result_handler): def handle(*args): self._result_handler(*args) result_handler(*args) self._server = RideListenerServer(RideListenerHandler, handle) self._server_thread = threading.Thread(target=self._server.serve_forever) self._server_thread.setDaemon(True) self._server_thread.start() self.port = self._server.server_address[1] def _result_handler(self, event, *args): if event == 'pid': self._pid_to_kill = int(args[0]) if event == 'port' and self._process: self._process.set_port(args[0]) self._send_pause_on_failure_information() if event == 'start_test': longname = args[1]['longname'] testname = args[0] self._results.set_running(self._get_test_controller(longname, testname)) if event == 'end_test': longname = args[1]['longname'] testname = args[0] if args[1]['status'] == 'PASS': self._results.set_passed(self._get_test_controller(longname, testname)) else: self._results.set_failed(self._get_test_controller(longname, testname)) def _get_test_controller(self, longname, testname = None): ret = self._chief.find_controller_by_longname(longname, testname) return ret def clear_server(self): self._server = None def shutdown_server(self): if self._server: self._server.shutdown() def test_execution_started(self): self._results.test_execution_started() def kill_process(self): if self._process: self._process.kill(force=True) def set_pause_on_failure(self, pause): self._pause_on_failure = pause self._send_pause_on_failure_information() def _send_pause_on_failure_information(self): if self._process: self._process.pause_on_failure(self._pause_on_failure) def send_stop_signal(self): if self._process: self._process.kill(killer_pid=self._pid_to_kill) def send_pause_signal(self): if self._process: self._process.pause() def send_continue_signal(self): if self._process: self._process.resume() def send_step_next_signal(self): if self._process: self._process.step_next() def send_step_over_signal(self): if self._process: self._process.step_over() def run_command(self, command, cwd): self._pid_to_kill = None self._process = Process(cwd) self._process.run_command(command) def get_command(self, profile, pythonpath, monitor_width, test_names): '''Return the command (as a list) used to run the test''' command = profile.get_command_prefix()[:] argfile = os.path.join(self._output_dir, "argfile.txt") command.extend(["--argumentfile", argfile]) command.extend(["--listener", self._get_listener_to_cmd()]) command.append(self._get_suite_source_for_command()) self._write_argfile(argfile, self._create_standard_args(command, profile, pythonpath, monitor_width, test_names)) return command def get_message_log_level(self, command): min_log_level_number = LEVELS['INFO'] if '-L' in command: switch = '-L' elif '--loglevel' in command: switch = '--loglevel' else: return min_log_level_number i = command.index(switch) if len(command) == i: return level = command[i+1].upper().split(':')[0] return LEVELS.get(level, min_log_level_number) def _get_listener_to_cmd(self): path = os.path.abspath(TestRunnerAgent.__file__) if path[-1] == 'c': path = path[:-1] return '%s:%s' % (path, self.port) def _get_suite_source_for_command(self): cur = os.path.abspath(os.path.curdir) source = os.path.abspath(self._chief.suite.source) if not utils.is_same_drive(cur, source): return source return os.path.abspath(self._chief.suite.source) def _create_standard_args(self, command, profile, pythonpath, monitor_width, test_names): standard_args = [] standard_args.extend(profile.get_custom_args()) self._add_tmp_outputdir_if_not_given_by_user(command, standard_args) self._add_pythonpath_if_in_settings_and_not_given_by_user(command, standard_args, pythonpath) standard_args.extend(["--monitorcolors", "off"]) standard_args.extend(["--monitorwidth", monitor_width]) for tc in test_names: standard_args += ['--test', tc] return standard_args def _add_tmp_outputdir_if_not_given_by_user(self, command, standard_args): if "--outputdir" not in command and "-d" not in command: standard_args.extend(["--outputdir", self._output_dir]) def _add_pythonpath_if_in_settings_and_not_given_by_user(self, command, standard_args, pythonpath): if '--pythonpath' in command: return if '-P' in command: return if not pythonpath: return standard_args.extend(['--pythonpath', ':'.join(pythonpath)]) def _write_argfile(self, argfile, args): f = codecs.open(argfile, "w", "utf-8") f.write("\n".join(args)) f.close() def get_output_and_errors(self): return self._process.get_output(), self._process.get_errors() def is_running(self): return self._process and self._process.is_alive() def command_ended(self): self._process = None
def setUp(self): self._results = TestExecutionResults() self._test = object() self._test2 = object()
class TestExecutionResultTestCase(unittest.TestCase): def setUp(self): self._results = TestExecutionResults() self._test = object() self._test2 = object() def test_running_test(self): self._results.set_running(self._test) self._expect_running(self._test) self._results.set_passed(self._test) self._expect_passed(self._test) def _expect_passed(self, test): self.assertFalse(self._results.is_running(test)) self.assertTrue(self._results.has_passed(test)) self.assertFalse(self._results.has_failed(test)) def _expect_running(self, test): self.assertTrue(self._results.is_running(test)) self.assertFalse(self._results.has_passed(test)) self.assertFalse(self._results.has_failed(test)) def test_running_test_that_fails(self): self._results.set_running(self._test) self._expect_running(self._test) self._results.set_failed(self._test) self._expect_failed(self._test) def _expect_failed(self, test): self.assertFalse(self._results.is_running(test)) self.assertFalse(self._results.has_passed(test)) self.assertTrue(self._results.has_failed(test)) def test_running_two_tests(self): self._results.set_running(self._test) self._expect_running(self._test) self._expect_no_result(self._test2) self._results.set_failed(self._test) self._expect_failed(self._test) self._results.set_running(self._test2) self._expect_running(self._test2) self._expect_failed(self._test) self._results.set_passed(self._test2) self._expect_passed(self._test2) self._expect_failed(self._test) def test_clearing_results(self): self._results.set_running(self._test) self._results.set_passed(self._test) self._results.set_running(self._test2) self._results.set_passed(self._test2) self._results.clear() self._expect_no_result(self._test) self._expect_no_result(self._test2) def _expect_no_result(self, test): self.assertFalse(self._results.is_running(test)) self.assertFalse(self._results.has_passed(test)) self.assertFalse(self._results.has_failed(test))
class TestRunner(object): def __init__(self, project): self._process = None self._server = None self._server_thread = None self._pause_on_failure = False self._pid_to_kill = None self._results = TestExecutionResults() self._port = None self._project = project self.profiles = {} self._pause_longname = None self._pause_testname = None def enable(self, result_handler): self._start_listener_server(result_handler) def add_profile(self, name, item): self.profiles[name] = item def get_profile(self, name): return self.profiles[name] def get_profile_names(self): return sorted(self.profiles.keys()) def _start_listener_server(self, result_handler): def handle(*args): self._result_handler(*args) result_handler(*args) self._server = RideListenerServer(RideListenerHandler, handle) self._server_thread = threading.Thread( target=self._server.serve_forever) self._server_thread.setDaemon(True) self._server_thread.start() self._port = self._server.server_address[1] def _result_handler(self, event, *args): if event == 'pid': self._pid_to_kill = int(args[0]) if event == 'port' and self._process: self._process.set_port(args[0]) if event == 'start_test': longname = args[1]['longname'] testname = args[0] self._results.set_running( self._get_test_controller(longname, testname)) self._pause_longname = longname self._pause_testname = testname if event == 'continue': self._results.set_running( self._get_test_controller(self._pause_longname, self._pause_testname)) if event == 'paused': self._results.set_paused( self._get_test_controller(self._pause_longname, self._pause_testname)) if event == 'end_test': longname = args[1]['longname'] testname = args[0] if args[1]['status'] == 'PASS': self._results.set_passed( self._get_test_controller(longname, testname)) else: self._results.set_failed( self._get_test_controller(longname, testname)) def _get_test_controller(self, longname, testname=None): ret = self._project.find_controller_by_longname(longname, testname) return ret def clear_server(self): self._server = None def shutdown_server(self): if self._server: self._server.shutdown() def test_execution_started(self): self._results.test_execution_started() def kill_process(self): if self._process: self._process.kill(force=True) def send_pause_on_failure(self, pause): if self._process: self._process.pause_on_failure(pause) def send_stop_signal(self): if self._process: self._process.kill(killer_pid=self._pid_to_kill) def send_pause_signal(self): if self._process: self._process.pause() def send_continue_signal(self): if self._process: self._process.resume() def send_step_next_signal(self): if self._process: self._process.step_next() def send_step_over_signal(self): if self._process: self._process.step_over() def run_command(self, command, cwd): self._pid_to_kill = None self._process = Process(cwd) self._process.run_command(command) def get_output_and_errors(self, profile): stdout, stderr, returncode = self._process.get_output(), \ self._process.get_errors(), \ self._process.get_returncode() error, log_message = profile.format_error(stderr, returncode) return stdout, error, log_message def get_listener_port(self): return self._port def is_running(self): return self._process and self._process.is_alive() def command_ended(self): self._process = None