diff --git a/parse_test_results.py b/parse_test_results.py new file mode 100644 index 0000000000000000000000000000000000000000..0682eb0871ecb6029638a3b0fcd2e96ef3050e36 --- /dev/null +++ b/parse_test_results.py @@ -0,0 +1,109 @@ +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() diff --git a/writeExcel.py b/writeExcel.py index 662dd0d9b7b7b139ef5951af4e9eac8e1d1257bb..76192e1d82ed66e0e4e13fa89f5e120d9ec047c5 100644 --- a/writeExcel.py +++ b/writeExcel.py @@ -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 @@ -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