def retry_test(self, retry_type=None, prompt_message=""): if self.retry_type == TestClass.RT_ABORT or retry_type == TestClass.RT_ABORT: raise SequenceAbort("Sequence Aborted Automatically") elif self.retry_type == TestClass.RT_FAIL or retry_type == TestClass.RT_FAIL: return False elif retry_type == TestClass.RT_RETRY: return True elif retry_type == TestClass.RT_PROMPT: print(prompt_message) status, resp = user_retry_abort_fail(prompt_message) # TODO Fix me if resp == "ABORT": raise SequenceAbort("Sequence Aborted By User") else: return resp == "RETRY"
def stop(self): """This function is called in case of unusual termination, and runs in the main thread""" self.sequencer._handle_sequence_abort() pub.sendMessage("Sequence_Abort", exception=SequenceAbort("Application Closing")) return 11
def run_once(self): """ Runs through the tests once as are pushed onto the context stack. Ie. One run through of the tests Once finished sets the status to Finished """ while self.context: if self.status == "Running": try: top = self.context.top() if top.index >= len( top.testlist ): # Finished tests in the test list self.context.pop() pub.sendMessage( "TestList_Complete", data=top.testlist, test_index=self.levels(), ) top.testlist.exit() if self.context: self.context.top().index += 1 elif isinstance(top.current(), TestClass): if self.run_test(): top.index += 1 else: if not self.retry_prompt(): # mark the test as failed and continue. else will loop and try again self.tests_failed += 1 top.index += 1 elif isinstance(top.current(), TestList): pub.sendMessage( "TestList_Start", data=top.current(), test_index=self.levels(), ) top.current().enter() self.context.push(top.current()) else: raise SequenceAbort("Unknown Test Item Type") except BaseException as e: pub.sendMessage( "Test_Exception", exception=sys.exc_info()[1], test_index=self.levels(), ) pub.sendMessage("Sequence_Abort", exception=e) self._handle_sequence_abort() return elif self.status != "Aborted": time.sleep(0.1) else: return self.status = "Finished"
def retry_prompt(self): """Prompt the user when something goes wrong. For retry return True, to fail return False and to abort raise and abort exception. Respect the non_interactive flag, which can be set by the command line option --non-interactive""" if self.non_interactive: return False status, resp = user_retry_abort_fail(msg="") if resp == "ABORT": raise SequenceAbort("Sequence Aborted By User") else: return resp == "RETRY"
def stop(self): """This function is called in case of unusual termination, and runs in the main thread""" self.sequencer._handle_sequence_abort() pub.sendMessage("Sequence_Abort", exception=SequenceAbort("Application Closing")) self.loop.stop() for _ in range(15): if self.loop.is_running(): # Wait max 15 seconds for loop to end sleep(1) else: break try: self.loop.close() except Exception: pass # If the thread has hung, or reached an uninterruptable state, ignore it, it'll be force terminated at the end anyway return 11
def run_test(self): """ Runs the active test in the stack. Should only be called if the top of the stack is a TestClass :return: True if test passed, False if test failed or had an exception """ active_test = self.context.top().current() active_test_status = "PENDING" pub.sendMessage("Test_Start", data=active_test, test_index=self.levels()) if active_test.skip: self.tests_skipped += 1 active_test_status = "SKIP" pub.sendMessage("Test_Skip", data=active_test, test_index=self.levels()) pub.sendMessage("Test_Complete", data=active_test, test_index=self.levels(), status=active_test_status) return True attempts = 0 abort_exceptions = [SequenceAbort, KeyboardInterrupt] abort_exceptions.extend(active_test.abort_exceptions) while True: attempts += 1 # Retry exceeded test only when user is not involved in retry process try: if attempts > active_test.attempts and attempts != -1: break self.chk_fail, self.chk_pass = 0, 0 # Run the test try: for index_context, current_level in enumerate(self.context): current_level.current().set_up() active_test.test() finally: for current_level in self.context[index_context::-1]: current_level.current().tear_down() if not self.chk_fail: active_test_status = "PASS" self.tests_passed += 1 else: active_test_status = "FAIL" self.tests_failed += 1 break except CheckFail: if self.ABORT: # Program force quit active_test_status = "ERROR" raise SequenceAbort("Sequence Aborted") # Retry Logic for failed checks active_test_status = "FAIL" except tuple(abort_exceptions): if self.ABORT: # Program force quit active_test_status = "ERROR" raise SequenceAbort("Sequence Aborted") pub.sendMessage("Test_Exception", exception=sys.exc_info()[1], test_index=self.levels()) attempts = 0 active_test_status = "ERROR" if not self.retry_prompt(): self.tests_errored += 1 break # Retry logic for exceptions except BaseException as e: active_test_status = "ERROR" if self.ABORT: # Program force quit raise SequenceAbort("Sequence Aborted") pub.sendMessage("Test_Exception", exception=sys.exc_info()[1], test_index=self.levels()) # Retry Logic pub.sendMessage("Test_Retry", data=active_test, test_index=self.levels()) pub.sendMessage("Test_Complete", data=active_test, test_index=self.levels(), status=active_test_status) return active_test_status == "PASS"