Loading .gitignore 0 → 100644 +3 −0 Original line number Diff line number Diff line *.xlsx __pycache__/ .vscode/ No newline at end of file parseTestResults.pydeleted 100644 → 0 +0 −88 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") # 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.robotFile = parts[len(parts) - 1] # Tests tests = soup.find_all("test") for test in tests: self.testEntries.append(self.createTestEntry(test)) # Write tests ew = ExcelWriter() for entry in self.testEntries: ew.writeTestEntry(entry) ew.save() def createTestEntry(self, xmlObj): """ 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 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, self.api, self.robotFile) 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 parse_test_results.py +48 −61 Original line number Diff line number Diff line from bs4 import BeautifulSoup from sys import argv from testEntry import TestEntry from writeExcel import ExcelWriter """ Tool entry point """ import sys 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 from bs4 import BeautifulSoup from test_entry import TestEntry from write_excel import ExcelWriter 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): """ Parser taking a file name (of the XML output from robot), and extracts relevant information, eventually creating a list of TestEntry objects """ def __init__(self, input_file, output_file): self.test_entries = [] self.load_file(fname) self.load_file(input_file) self.api = "" self.output_file = output_file self.robot_file_contents = "" def load_file(self, fname): self.contents = "" """ Load xml file """ with open(fname, "r", encoding="utf8") as f: self.contents = f.read() with open(fname, "r", encoding="utf8") as robot_file: self.robot_file_contents = robot_file.read() if self.contents == "": if self.robot_file_contents == "": print("Empty file {}".format(fname)) exit(-1) sys.exit(-1) def run_parser(self): soup = BeautifulSoup(self.contents, "lxml") """ Run parser, extracting all info to create the test entries """ soup = BeautifulSoup(self.robot_file_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] self.robot_file_contents = parts[len(parts) - 1] # Tests tests = soup.find_all("test") Loading @@ -54,10 +57,10 @@ class TestOutputParser: self.test_entries.append(self.create_test_entry(test)) # Write tests ew = ExcelWriter() excel_writer = ExcelWriter(self.output_file) for entry in self.test_entries: ew.write_test_entry(entry) ew.save() excel_writer.write_test_entry(entry) excel_writer.save() def create_test_entry(self, xml_obj): """ Loading @@ -66,44 +69,28 @@ class TestOutputParser: """ # 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) match_group = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) test_id = match_group.group(1) name = xml_obj["name"] #retrieve status and error message (if FAIL) statusObj = xml_obj.find("status", recursive=False) cts = statusObj.contents status_obj = xml_obj.find("status", recursive=False) cts = status_obj.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) result = status_obj["status"] return TestEntry(test_id, name, (result, error_msg), (self.api, self.robot_file_contents)) 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', parser = argparse.ArgumentParser(description='Robot Test Reporter written in Python.\n' 'Produces an xlsx file from a robot XML ' 'output file.\n' 'The command outputs to a new xlslx file if it ' 'does not exist, or appends to an existing one.') parser.add_argument('input_file', help='XML file generated by Robot') parser.add_argument('-o', dest='output_file', default='testResults.xlsx', help='output file name (default: testResults.xlsx)') args = parser.parse_args() TestOutputParser(argv[1]).run_parser() TestOutputParser(args.input_file, args.output_file).run_parser() testEntry.pydeleted 100644 → 0 +0 −21 Original line number Diff line number Diff line class TestEntry: def __init__(self, id, name, result, errorMsg, api, robotFile): self.id = id self.name = name self.result = result self.errorMsg = errorMsg self.api = api self.robotFile = robotFile def __str__(self): baseStr = "[{}] {}:{}".format(self.id, self.name, self.result) if self.errorMsg != "": return "{}: {} ({}/{})".format(baseStr, self.errorMsg, self.api, self.robotFile) else: return baseStr def __repr__(self): return "{}: {}".format(self.name, self.result) def asList(self): return [self.id, self.name, self.result, self.errorMsg, self.api, self.robotFile] No newline at end of file test_entry.py 0 → 100644 +38 −0 Original line number Diff line number Diff line """ Contains utility class `TestEntry` """ class TestEntry: """ Models a single entry (row) in the resulting xlsx file. Contains all the relevant information about a single test: id: Test ID name: Test Name result: PASS/FAIL error_message: In case of FAIL, contains reason robot_file: Robot file containing the test """ def __init__(self, test_id, name, status, test_info): self.test_id = test_id self.name = name self.result = status[0] self.error_message = status[1] self.api = test_info[0] self.robot_file = test_info[1] def __str__(self): base_str = "[{}] {}:{}".format(self.test_id, self.name, self.result) if self.error_message != "": return "{}: {} ({}/{})".format(base_str, self.error_message, self.api, self.robot_file) return base_str def __repr__(self): return "{}: {}".format(self.name, self.result) def as_list(self): """ Construct a list-representation of the entry """ return [self.test_id, self.name, self.result, self.error_message, self.api, self.robot_file] Loading
.gitignore 0 → 100644 +3 −0 Original line number Diff line number Diff line *.xlsx __pycache__/ .vscode/ No newline at end of file
parseTestResults.pydeleted 100644 → 0 +0 −88 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") # 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.robotFile = parts[len(parts) - 1] # Tests tests = soup.find_all("test") for test in tests: self.testEntries.append(self.createTestEntry(test)) # Write tests ew = ExcelWriter() for entry in self.testEntries: ew.writeTestEntry(entry) ew.save() def createTestEntry(self, xmlObj): """ 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 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, self.api, self.robotFile) 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
parse_test_results.py +48 −61 Original line number Diff line number Diff line from bs4 import BeautifulSoup from sys import argv from testEntry import TestEntry from writeExcel import ExcelWriter """ Tool entry point """ import sys 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 from bs4 import BeautifulSoup from test_entry import TestEntry from write_excel import ExcelWriter 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): """ Parser taking a file name (of the XML output from robot), and extracts relevant information, eventually creating a list of TestEntry objects """ def __init__(self, input_file, output_file): self.test_entries = [] self.load_file(fname) self.load_file(input_file) self.api = "" self.output_file = output_file self.robot_file_contents = "" def load_file(self, fname): self.contents = "" """ Load xml file """ with open(fname, "r", encoding="utf8") as f: self.contents = f.read() with open(fname, "r", encoding="utf8") as robot_file: self.robot_file_contents = robot_file.read() if self.contents == "": if self.robot_file_contents == "": print("Empty file {}".format(fname)) exit(-1) sys.exit(-1) def run_parser(self): soup = BeautifulSoup(self.contents, "lxml") """ Run parser, extracting all info to create the test entries """ soup = BeautifulSoup(self.robot_file_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] self.robot_file_contents = parts[len(parts) - 1] # Tests tests = soup.find_all("test") Loading @@ -54,10 +57,10 @@ class TestOutputParser: self.test_entries.append(self.create_test_entry(test)) # Write tests ew = ExcelWriter() excel_writer = ExcelWriter(self.output_file) for entry in self.test_entries: ew.write_test_entry(entry) ew.save() excel_writer.write_test_entry(entry) excel_writer.save() def create_test_entry(self, xml_obj): """ Loading @@ -66,44 +69,28 @@ class TestOutputParser: """ # 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) match_group = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) test_id = match_group.group(1) name = xml_obj["name"] #retrieve status and error message (if FAIL) statusObj = xml_obj.find("status", recursive=False) cts = statusObj.contents status_obj = xml_obj.find("status", recursive=False) cts = status_obj.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) result = status_obj["status"] return TestEntry(test_id, name, (result, error_msg), (self.api, self.robot_file_contents)) 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', parser = argparse.ArgumentParser(description='Robot Test Reporter written in Python.\n' 'Produces an xlsx file from a robot XML ' 'output file.\n' 'The command outputs to a new xlslx file if it ' 'does not exist, or appends to an existing one.') parser.add_argument('input_file', help='XML file generated by Robot') parser.add_argument('-o', dest='output_file', default='testResults.xlsx', help='output file name (default: testResults.xlsx)') args = parser.parse_args() TestOutputParser(argv[1]).run_parser() TestOutputParser(args.input_file, args.output_file).run_parser()
testEntry.pydeleted 100644 → 0 +0 −21 Original line number Diff line number Diff line class TestEntry: def __init__(self, id, name, result, errorMsg, api, robotFile): self.id = id self.name = name self.result = result self.errorMsg = errorMsg self.api = api self.robotFile = robotFile def __str__(self): baseStr = "[{}] {}:{}".format(self.id, self.name, self.result) if self.errorMsg != "": return "{}: {} ({}/{})".format(baseStr, self.errorMsg, self.api, self.robotFile) else: return baseStr def __repr__(self): return "{}: {}".format(self.name, self.result) def asList(self): return [self.id, self.name, self.result, self.errorMsg, self.api, self.robotFile] No newline at end of file
test_entry.py 0 → 100644 +38 −0 Original line number Diff line number Diff line """ Contains utility class `TestEntry` """ class TestEntry: """ Models a single entry (row) in the resulting xlsx file. Contains all the relevant information about a single test: id: Test ID name: Test Name result: PASS/FAIL error_message: In case of FAIL, contains reason robot_file: Robot file containing the test """ def __init__(self, test_id, name, status, test_info): self.test_id = test_id self.name = name self.result = status[0] self.error_message = status[1] self.api = test_info[0] self.robot_file = test_info[1] def __str__(self): base_str = "[{}] {}:{}".format(self.test_id, self.name, self.result) if self.error_message != "": return "{}: {} ({}/{})".format(base_str, self.error_message, self.api, self.robot_file) return base_str def __repr__(self): return "{}: {}".format(self.name, self.result) def as_list(self): """ Construct a list-representation of the entry """ return [self.test_id, self.name, self.result, self.error_message, self.api, self.robot_file]