Loading parseTestResults.py 0 → 100644 +75 −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 from sys import exit import re 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.testEntries = [] 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") tests = soup.find_all("test") for test in tests: self.testEntries.append(createTestEntry(test)) # Write tests ew = ExcelWriter() for entry in self.testEntries: ew.writeTestEntry(entry) ew.save() def createTestEntry(xmlObj): # retrieve ID and name idRaw = xmlObj.find("doc", recursive=False).contents mg = re.search(r"Test ID: ([0-9\.]*)$", idRaw[0].string, re.MULTILINE) testId = mg.group(1) name = xmlObj["name"] #retrieve status and error message (if FAIL) statusObj = xmlObj.find("status", recursive=False) cts = statusObj.contents errorMsg = cts[0] if len(cts) > 0 else "" result = statusObj["status"] return TestEntry(testId, name, result, errorMsg) def display_usage(): print(usage_str) if __name__ == "__main__": if len(argv) < 2: display_usage() exit() TestOutputParser(argv[1]).run_parser() No newline at end of file testEntry.py 0 → 100644 +20 −0 Original line number Diff line number Diff line class TestEntry: def __init__(self, id, name, result, errorMsg=""): self.id = id self.name = name self.result = result self.errorMsg = errorMsg def __str__(self): baseStr = "[{}] {}:{}".format(self.id, self.name, self.result) if self.errorMsg != "": return "{}: {}".format(baseStr, self.errorMsg) else: return baseStr def __repr__(self): return "{}: {}".format(self.name, self.result) def asList(self): return [self.id, self.name, self.result, self.errorMsg] No newline at end of file writeExcel.py 0 → 100644 +60 −0 Original line number Diff line number Diff line from openpyxl import Workbook, load_workbook from openpyxl.utils import get_column_letter from openpyxl.styles import Font from openpyxl.styles.fills import Stop, PatternFill fname = 'testResults.xlsx' class ExcelWriter: """ Utility class which writes `TestEntry` objects to an excel file. Creates file if it does not exist. """ PASS_COL = "00FF00" FAIL_COL = "FF0000" def __init__(self): self.wb = getWorkbook() self.ws = self.wb.active def getLastRow(self): for cell in self.ws["A"]: if cell.value is None: return cell.row return cell.row + 1 def writeTestEntry(self, testEntry): lastRow = self.getLastRow() cellCol = ExcelWriter.PASS_COL if testEntry.result == "PASS" else ExcelWriter.FAIL_COL for col, cellValue in zip(self.ws.iter_cols(min_row=lastRow, max_col=4, max_row=lastRow), testEntry.asList()): for cell in col: cell.value = cellValue cell.fill = PatternFill("solid", fgColor=cellCol)# cellCol def save(self): self.wb.save(filename = fname) def initWorkbook(wb): """ Writes column headers to ws """ headers = [("Test ID", 10), ("Test name", 80), ("Result", 6), ("Error Message", 100)] headerFont = Font(bold=True) ws = wb.active for col, header in zip(ws.iter_cols(min_row=1, max_col=4, max_row=1), headers): for cell in col: headerName = header[0] colsize = header[1] ws.column_dimensions[get_column_letter(cell.column)].width = colsize cell.value = headerName cell.font = headerFont def getWorkbook(): try: wb = load_workbook(filename = fname) return wb except FileNotFoundError: wb = Workbook() initWorkbook(wb) return wb No newline at end of file Loading
parseTestResults.py 0 → 100644 +75 −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 from sys import exit import re 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.testEntries = [] 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") tests = soup.find_all("test") for test in tests: self.testEntries.append(createTestEntry(test)) # Write tests ew = ExcelWriter() for entry in self.testEntries: ew.writeTestEntry(entry) ew.save() def createTestEntry(xmlObj): # retrieve ID and name idRaw = xmlObj.find("doc", recursive=False).contents mg = re.search(r"Test ID: ([0-9\.]*)$", idRaw[0].string, re.MULTILINE) testId = mg.group(1) name = xmlObj["name"] #retrieve status and error message (if FAIL) statusObj = xmlObj.find("status", recursive=False) cts = statusObj.contents errorMsg = cts[0] if len(cts) > 0 else "" result = statusObj["status"] return TestEntry(testId, name, result, errorMsg) def display_usage(): print(usage_str) if __name__ == "__main__": if len(argv) < 2: display_usage() exit() TestOutputParser(argv[1]).run_parser() No newline at end of file
testEntry.py 0 → 100644 +20 −0 Original line number Diff line number Diff line class TestEntry: def __init__(self, id, name, result, errorMsg=""): self.id = id self.name = name self.result = result self.errorMsg = errorMsg def __str__(self): baseStr = "[{}] {}:{}".format(self.id, self.name, self.result) if self.errorMsg != "": return "{}: {}".format(baseStr, self.errorMsg) else: return baseStr def __repr__(self): return "{}: {}".format(self.name, self.result) def asList(self): return [self.id, self.name, self.result, self.errorMsg] No newline at end of file
writeExcel.py 0 → 100644 +60 −0 Original line number Diff line number Diff line from openpyxl import Workbook, load_workbook from openpyxl.utils import get_column_letter from openpyxl.styles import Font from openpyxl.styles.fills import Stop, PatternFill fname = 'testResults.xlsx' class ExcelWriter: """ Utility class which writes `TestEntry` objects to an excel file. Creates file if it does not exist. """ PASS_COL = "00FF00" FAIL_COL = "FF0000" def __init__(self): self.wb = getWorkbook() self.ws = self.wb.active def getLastRow(self): for cell in self.ws["A"]: if cell.value is None: return cell.row return cell.row + 1 def writeTestEntry(self, testEntry): lastRow = self.getLastRow() cellCol = ExcelWriter.PASS_COL if testEntry.result == "PASS" else ExcelWriter.FAIL_COL for col, cellValue in zip(self.ws.iter_cols(min_row=lastRow, max_col=4, max_row=lastRow), testEntry.asList()): for cell in col: cell.value = cellValue cell.fill = PatternFill("solid", fgColor=cellCol)# cellCol def save(self): self.wb.save(filename = fname) def initWorkbook(wb): """ Writes column headers to ws """ headers = [("Test ID", 10), ("Test name", 80), ("Result", 6), ("Error Message", 100)] headerFont = Font(bold=True) ws = wb.active for col, header in zip(ws.iter_cols(min_row=1, max_col=4, max_row=1), headers): for cell in col: headerName = header[0] colsize = header[1] ws.column_dimensions[get_column_letter(cell.column)].width = colsize cell.value = headerName cell.font = headerFont def getWorkbook(): try: wb = load_workbook(filename = fname) return wb except FileNotFoundError: wb = Workbook() initWorkbook(wb) return wb No newline at end of file