Loading parse_test_results.py 0 → 100644 +109 −0 Original line number Diff line number Diff line from bs4 import BeautifulSoup from sys import argv from testEntry import TestEntry from writeExcel import ExcelWriter import re import argparse usage_str = """ ===================================== Robot Test Reporter written in Python ===================================== Usage python parseTestResults.py output.xml where output.xml is the xml file generated by robot The command outputs to a new xlslx file if it does not exist, or appends to an existing one. """ class TestOutputParser: def __init__(self, fname): self.test_entries = [] self.load_file(fname) def load_file(self, fname): self.contents = "" with open(fname, "r", encoding="utf8") as f: self.contents = f.read() if self.contents == "": print("Empty file {}".format(fname)) exit(-1) def run_parser(self): soup = BeautifulSoup(self.contents, "lxml") # Suite information suite = soup.find("suite") path = suite["source"] # TODO This might be an issue later on. In Unix-style paths the separator is a forward slash parts = path.split("\\") # Extract info for test entries self.api = parts[len(parts) - 2] self.robot_file = parts[len(parts) - 1] # Tests tests = soup.find_all("test") for test in tests: self.test_entries.append(self.create_test_entry(test)) # Write tests ew = ExcelWriter() for entry in self.test_entries: ew.write_test_entry(entry) ew.save() def create_test_entry(self, xml_obj): """ Takes the xml entry corresponding to the test from the output file, and returns a TestEntry object with the relevant information extracted. """ # retrieve ID and name id_raw = xml_obj.find("doc", recursive=False).contents mg = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) test_id = mg.group(1) name = xml_obj["name"] #retrieve status and error message (if FAIL) statusObj = xml_obj.find("status", recursive=False) cts = statusObj.contents error_msg = cts[0] if len(cts) > 0 else "" result = statusObj["status"] return TestEntry(test_id, name, result, error_msg, self.api, self.robot_file) def display_usage(): print(usage_str) if __name__ == "__main__": usage_str = """ ===================================== Robot Test Reporter written in Python ===================================== Usage python parseTestResults.py output.xml where output.xml is the xml file generated by robot The command outputs to a new xlslx file if it does not exist, or appends to an existing one. """ parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('-o', dest='fname', action='store_const', default='testResults.xlsx', help='output file name (default: testResults.xlsx)') args = parser.parse_args() TestOutputParser(argv[1]).run_parser() writeExcel.py +12 −11 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ class ExcelWriter: self.wb = getWorkbook() self.ws = self.wb.active def getEntryWithId(self, id): def get_entry_with_id(self, id): """ When inserting an entry, it might be a test being re-run. In that case, the row containing that test needs to be updated, as opposed to appending Loading @@ -32,32 +32,33 @@ class ExcelWriter: return cell.row return -1 def getLastRow(self): def get_last_row(self): for cell in self.ws["A"]: if cell.value is None: return cell.row return cell.row + 1 def writeTestEntry(self, testEntry): existingEntryRow = self.getEntryWithId(testEntry.id) lastRow = self.getLastRow() def writeTestEntry(self, test_entry): existing_entry_row = self.get_entry_with_id(test_entry.id) last_row = self.get_last_row() # Use the above two values to pick a row entryRow = existingEntryRow if existingEntryRow != -1 else lastRow entry_row = existing_entry_row if existing_entry_row != -1 else last_row # Pick a cell color based on test outcome cellCol = ExcelWriter.PASS_COL if testEntry.result == "PASS" else ExcelWriter.FAIL_COL cell_col = ExcelWriter.PASS_COL if test_entry.result == "PASS" else ExcelWriter.FAIL_COL # Test entry as a list entryVals = testEntry.asList() entry_vals = test_entry.asList() for col, cellValue in zip(self.ws.iter_cols(min_row=entryRow, max_col=len(entryVals), max_row=entryRow), entryVals): for col, cell_vale in zip(self.ws.iter_cols(min_row=entry_row, max_col=len(entry_vals), max_row=entry_row), entry_vals): for cell in col: cell.value = cellValue cell.fill = PatternFill("solid", fgColor=cellCol)# cellCol cell.value = cell_vale cell.fill = PatternFill("solid", fgColor=cell_col)# cellCol def save(self): self.wb.save(filename = fname) def initWorkbook(wb): """ Writes column headers to ws Loading Loading
parse_test_results.py 0 → 100644 +109 −0 Original line number Diff line number Diff line from bs4 import BeautifulSoup from sys import argv from testEntry import TestEntry from writeExcel import ExcelWriter import re import argparse usage_str = """ ===================================== Robot Test Reporter written in Python ===================================== Usage python parseTestResults.py output.xml where output.xml is the xml file generated by robot The command outputs to a new xlslx file if it does not exist, or appends to an existing one. """ class TestOutputParser: def __init__(self, fname): self.test_entries = [] self.load_file(fname) def load_file(self, fname): self.contents = "" with open(fname, "r", encoding="utf8") as f: self.contents = f.read() if self.contents == "": print("Empty file {}".format(fname)) exit(-1) def run_parser(self): soup = BeautifulSoup(self.contents, "lxml") # Suite information suite = soup.find("suite") path = suite["source"] # TODO This might be an issue later on. In Unix-style paths the separator is a forward slash parts = path.split("\\") # Extract info for test entries self.api = parts[len(parts) - 2] self.robot_file = parts[len(parts) - 1] # Tests tests = soup.find_all("test") for test in tests: self.test_entries.append(self.create_test_entry(test)) # Write tests ew = ExcelWriter() for entry in self.test_entries: ew.write_test_entry(entry) ew.save() def create_test_entry(self, xml_obj): """ Takes the xml entry corresponding to the test from the output file, and returns a TestEntry object with the relevant information extracted. """ # retrieve ID and name id_raw = xml_obj.find("doc", recursive=False).contents mg = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) test_id = mg.group(1) name = xml_obj["name"] #retrieve status and error message (if FAIL) statusObj = xml_obj.find("status", recursive=False) cts = statusObj.contents error_msg = cts[0] if len(cts) > 0 else "" result = statusObj["status"] return TestEntry(test_id, name, result, error_msg, self.api, self.robot_file) def display_usage(): print(usage_str) if __name__ == "__main__": usage_str = """ ===================================== Robot Test Reporter written in Python ===================================== Usage python parseTestResults.py output.xml where output.xml is the xml file generated by robot The command outputs to a new xlslx file if it does not exist, or appends to an existing one. """ parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('-o', dest='fname', action='store_const', default='testResults.xlsx', help='output file name (default: testResults.xlsx)') args = parser.parse_args() TestOutputParser(argv[1]).run_parser()
writeExcel.py +12 −11 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ class ExcelWriter: self.wb = getWorkbook() self.ws = self.wb.active def getEntryWithId(self, id): def get_entry_with_id(self, id): """ When inserting an entry, it might be a test being re-run. In that case, the row containing that test needs to be updated, as opposed to appending Loading @@ -32,32 +32,33 @@ class ExcelWriter: return cell.row return -1 def getLastRow(self): def get_last_row(self): for cell in self.ws["A"]: if cell.value is None: return cell.row return cell.row + 1 def writeTestEntry(self, testEntry): existingEntryRow = self.getEntryWithId(testEntry.id) lastRow = self.getLastRow() def writeTestEntry(self, test_entry): existing_entry_row = self.get_entry_with_id(test_entry.id) last_row = self.get_last_row() # Use the above two values to pick a row entryRow = existingEntryRow if existingEntryRow != -1 else lastRow entry_row = existing_entry_row if existing_entry_row != -1 else last_row # Pick a cell color based on test outcome cellCol = ExcelWriter.PASS_COL if testEntry.result == "PASS" else ExcelWriter.FAIL_COL cell_col = ExcelWriter.PASS_COL if test_entry.result == "PASS" else ExcelWriter.FAIL_COL # Test entry as a list entryVals = testEntry.asList() entry_vals = test_entry.asList() for col, cellValue in zip(self.ws.iter_cols(min_row=entryRow, max_col=len(entryVals), max_row=entryRow), entryVals): for col, cell_vale in zip(self.ws.iter_cols(min_row=entry_row, max_col=len(entry_vals), max_row=entry_row), entry_vals): for cell in col: cell.value = cellValue cell.fill = PatternFill("solid", fgColor=cellCol)# cellCol cell.value = cell_vale cell.fill = PatternFill("solid", fgColor=cell_col)# cellCol def save(self): self.wb.save(filename = fname) def initWorkbook(wb): """ Writes column headers to ws Loading