def format_api_calls(self): """When converted to string, the API requests and responses will be formatted.""" request1 = re.match(VPatterns.get_std_details_request()[0], self._details) request2 = re.match(VPatterns.get_std_details_request()[1], self._details) response = re.match(VPatterns.get_std_details_response(), self._details) if request1: # "Sending HTTP POST request to server_url: ..." if request1.group(2) != 'None': request_json = json.loads(request1.group(2)) self._request_url = request1.group(1) self._request_id = int(request_json['id']) self._request_method = request_json['method'] self._request_params = request_json['params'] elif request2: # "JSON-RPC-POST: method= ..." self._request_url = request2.group(2) self._request_id = int(request2.group(3)) self._request_method = request2.group(1) self._request_params = "" elif response: # "JSON-RPC-POST response: ..." string = response.group(1) json_response = json.loads(string) self._response_id = json_response['id'] if 'result' in json_response: self._response_result = json_response['result'] self._response_type = 'Result' elif 'error' in json_response: self._response_result = json_response['error'] self._response_type = 'Error'
def is_at2_formatting(self, filepath): """Determines if the logs are using the AT2 format.""" with open(filepath, 'r') as f: for line in f: if re.match(VPatterns.get_std(), line): if re.search(VPatterns.get_at2_time(), line): return True else: return False
def _handle_raw_traceback(self, unf_log): """Handle traceback operations. Since tracebacks are contained in multiple lines, the separate elements must be stored. They are identified as follows and can be prepended by the same leading characters:: Traceback (most recent call last): File "<file name>", line <line num>, in <func call> <line> ... <exception>: <description> Leading characters can be ``!``, ``|>``, etc. :rtype: str | list(str) | None :returns: unf_str if not part of a traceback :returns: None if unf_log is part of traceback but not exception :returns: list of log lines gathered from traceback if unf_log is the last line. """ output = "" if unf_log is None: return None # First line of traceback ('Traceback (most recent call last):') if self._lm.curr_log_type == VLogType.TRACEBACK: self._lm.hold = True self.tb_leading_char = re.match(VPatterns.get_traceback(), unf_log).group(1) self._store_log(unf_log) self.traceback_flag = True output = None # Non-traceback log line elif not self.traceback_flag: output = unf_log # Last line of traceback ('<exception>: <description') elif re.match(VPatterns.get_traceback_exception(), unf_log[len(self.tb_leading_char):]): output = self.stored_logs output.append(unf_log) self._lm.curr_log_type = VLogType.TRACEBACK self.stored_logs = [] self.traceback_flag = False self.tb_leading_char = "" self._lm.hold = False # Inner traceback element elif self._lm.curr_log_type == VLogType.OTHER and unf_log: self._store_log(unf_log) output = None # Traceback doesn't meet vl specifications elif self._lm.curr_log_type: self._lm.enqueue_log(self._pull_logs()) self._lm.hold = False output = unf_log return output
def test_get_patterns(self): dt_pattern = " ".join( ["\d{4}-\d{2}-\d{2}", "\d{2}:\d{2}:\d{2}\.\d{6}"]) type_pattern = "(DEBUG|INFO|NOTICE|WARNING|ERROR|CRITICAL)" source_pattern = "\[.*:.*\]" thread_pattern = "\[.*:.*\]" details_pattern = ".*" self.assertEqual(VPatterns.get_std_datetime(), dt_pattern) self.assertEqual(VPatterns.get_std_type(), type_pattern) self.assertEqual(VPatterns.get_std_source(), source_pattern) self.assertEqual(VPatterns.get_std_thread(), thread_pattern) self.assertEqual(VPatterns.get_std_details(), details_pattern)
def _create_log_line(self, unf_str, log_type): """Create the appropriate VLogLine object based on type. :param str unf_str: Unformatted VL log line :param VLogType log_type: Type of VLogLine object to create. :rtype: LogLine | None :returns: VLogLine if unf_str matches pattern of type and is in specified test case, else None """ if not log_type or not unf_str: return unf_str output = None # Standard Log Line if log_type in VPatterns.std_log_types( ) and self._hm.std_log_in_specified_testcase(): output = vlogline.Standard(unf_str, log_type) # Store Start time self._store_curr_time(output) # Associate Error with Header if self.SUMMARY and output and output.logtype == VLogType.ERROR: self._hm.add_error(output) # Traceback Log Lines elif log_type == VLogType.TRACEBACK and self._hm.std_log_in_specified_testcase( ): output = vlogline.Traceback(unf_str) # Step Header elif log_type == VLogType.STEP_H: fmt_log = vlogline.StepHeader(unf_str) output = self._hm.update_current_log(fmt_log) # Test Case Header elif log_type == VLogType.TEST_CASE_H: fmt_log = vlogline.TestCaseHeader(unf_str) output = self._hm.update_current_log(fmt_log) # Suite Header elif log_type == VLogType.SUITE_H: fmt_log = vlogline.SuiteHeader(unf_str) output = self._hm.update_current_log(fmt_log) # General Header elif log_type == VLogType.GENERAL_H: fmt_log = vlogline.GeneralHeader(unf_str) output = self._hm.update_current_log(fmt_log) # Other Log Line elif log_type == VLogType.OTHER and self._hm.std_log_in_specified_testcase( ): output = vlogline.Other(unf_str) if output: self._prev_fmt_log = output return output
def _parse_fields(self, unf_str): """Parse the string into the suite header fields. Fields:: Suite Name, Description :return a list of the suite header fields :rtype list(str) """ unf_str = unf_str.strip(self.BORDER_CHAR) _, desc_token = unf_str.split(": ") fields = [] suite_name = re.search(VPatterns.get_suite_name(), desc_token).group(0) fields.append(suite_name) fields.append(desc_token) return fields
def _store_curr_time(self, log): """Store the datetime object of the time from the current log or None if no time available.""" if self.SUMMARY: set_root = False if not self._hm.is_test_start_time_added(): set_root = True if isinstance(log, str): pattern = "^(" + VPatterns.get_std_datetime() + ")" m = re.match(pattern, log) if m and m.group(1): self._curr_time = vlogfield.Datetime(m.group(1)).datetime else: self._curr_time = log.datetime if isinstance(self._prev_fmt_log, vlogline.Header) or set_root: self._hm.start_time(self._curr_time, root=set_root)
def _parse_fields(self, unf_str): """Parse the string into the test case header fields. Fields:: Test Case Name, Number, Description :return a list of the test case header fields :rtype list(str) """ unf_str = unf_str.strip(self.BORDER_CHAR) unf_str = unf_str.lstrip("Test Case ") number, desc_token = unf_str.split(": ") case_name = re.search(VPatterns.get_test_case_name(), desc_token).group(0) fields = [] fields.append(case_name) fields.append(int(number)) fields.append(desc_token) return fields
def _parse_fields(self, unf_str_list): """Parse the list of strings into the header, steps, and exception fields. :param list(str) unf_str_list: Unformatted VL log line """ unf_header = unf_str_list[0] unf_steps = unf_str_list[1:-1] unf_exception = unf_str_list[-1] self.leading_chars = re.match(VPatterns.get_traceback(), unf_header).group(1) fmt_steps = [] for line1, line2 in zip(unf_steps[0::2], unf_steps[1::2]): line1 = self._remove_leading_chars(line1) line2 = self._remove_leading_chars(line2) step = "\n".join([line1, line2]) fmt_steps.append(vlogfield.TracebackStep(step, self.leading_chars)) unf_exception = self._remove_leading_chars(unf_exception) fmt_exception = vlogfield.TracebackException(unf_exception, self.leading_chars) return fmt_steps, fmt_exception
def _parse_fields(self, unf_str): """Parse the string into the step header fields. Fields:: Test Case Name, Number, Action, Expected Results :return a list of the step header fields :rtype list(str) """ line1, line2 = unf_str.split("\n") line1 = line1.strip(self.BORDER_CHAR) line2 = line2.strip(self.BORDER_CHAR) id, action = line1.split(": ") case_name = re.search(VPatterns.get_test_case_name(), id).group(0) number = re.search("\d+", id).group(0) _, expected_result = line2.split(": ") fields = [] fields.append(case_name) fields.append(int(number)) fields.append(action) fields.append(expected_result) return fields
def parse_step(self, tc_log_file, step_num): """Parses step logs from a test case log file. The specified step logs are placed into a file labelled with the step info, and the file will be located in a directory labelled tc_logs in the same directory as the log file. If the file already exists, the method will return. Example:: parse_step("~/logs/tc_logs/TcExample.log", step=0) # File location ~/logs/tc_logs/TcExample_Step-0.log :param str tc_log_file: Filepath of log file to be parsed. :param int step_num: Number of step to be parsed. """ tc_dir = os.path.dirname(tc_log_file) tc_filename = re.search("(Tc-?\w+).log", tc_log_file) step_filename = "%s_Step-%d.log" % (tc_filename.group(1), step_num) step_file = os.path.join(tc_dir, step_filename) if os.path.exists(step_file): return step_file else: open(step_file, "w").close() step_regex = VPatterns.get_step_header() tc_regex = VPatterns.get_test_case_header() in_specified_step = False completed_specified_step = False with open(tc_log_file) as original_file: for line in original_file: line = self._handle_raw_header(line.rstrip("\n")) if line is None: continue tc_match = re.match(tc_regex, line) step_match = re.match(step_regex, line) # Line is step if step_match: step = vlogline.StepHeader(line) # Step number matches current line if step_num == step.number: in_specified_step = True # New step is reached elif in_specified_step: completed_specified_step = True in_specified_step = False if in_specified_step: with open(step_file, "a") as f: f.write(str(step) + "\n") # Next Test Case reached elif tc_match and in_specified_step: completed_specified_step = True in_specified_step = False # Logs in specified step elif in_specified_step: with open(step_file, "a") as f: f.write(str(line) + "\n") if completed_specified_step: return step_file return step_file
def parse_test_case(self, log_file, tc_name=None, tc_num=None): """Parses test case logs from a log file. The specified test case logs are placed into a file labelled with the tc info, and the file will be located in a directory labelled tc_logs in the same directory as the log file. If the file already exists, the method will return. Example:: parse_test_case("~/logs/test.log", tc_name="TcExample") # File location ~/logs/tc_logs/TcExample.log :param str log_file: Filepath of log file to be parsed. :param str tc_name: Name of test case to be parsed, will supercede tc_num if specified :param int tc_num: Number of test case to be parsed. :returns: String filepath to parsed log file. """ dir = os.path.dirname(log_file) tc_dir = os.path.join(dir, "tc_logs") if not os.path.exists(tc_dir): os.mkdir(tc_dir) tc_filename = "%s.log" % (tc_name) if tc_name else ("Tc-%d.log" % (tc_num)) tc_file = os.path.join(tc_dir, tc_filename) if os.path.exists(tc_file): return tc_file else: open(tc_file, "w").close() step_regex = VPatterns.get_step_header() tc_regex = VPatterns.get_test_case_header() suite_regex = VPatterns.get_suite_header() general_regex = VPatterns.get_general_header() in_specified_tc = False completed_specified_tc = False with open(log_file) as original_file: for line in original_file: line = self._handle_raw_header(line.rstrip("\n")) if line is None: continue tc_match = re.match(tc_regex, line) step_match = re.match(step_regex, line) header_match = re.match( "".join([suite_regex, "|", general_regex]), line) # Line is test case if tc_match: tc = vlogline.TestCaseHeader(line) # TC name matches current line if tc_name and tc_name == tc.test_case_name: in_specified_tc = True # TC number matches current line elif tc_num >= 0 and tc_num == tc.number: in_specified_tc = True # New TC is reached elif in_specified_tc: completed_specified_tc = True in_specified_tc = False if in_specified_tc: with open(tc_file, "a") as f: f.write(str(tc) + "\n") # Line is a step header elif step_match and in_specified_tc: step = vlogline.StepHeader(line) with open(tc_file, "a") as f: f.write(str(step) + "\n") # New General or Suite header found to signal end of specified test case elif header_match and in_specified_tc: completed_specified_tc = True # Logs in specified test case elif in_specified_tc: with open(tc_file, "a") as f: f.write(str(line) + "\n") if completed_specified_tc: return tc_file return tc_file