Loading .gitignore 0 → 100644 +3 −0 Original line number Original line Diff line number Diff line *.xlsx __pycache__/ .vscode/ No newline at end of file parseTestResults.pydeleted 100644 → 0 +0 −88 Original line number Original line 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 Original line Diff line number Diff line from bs4 import BeautifulSoup """ from sys import argv Tool entry point from testEntry import TestEntry """ from writeExcel import ExcelWriter import sys import re import re import argparse import argparse from bs4 import BeautifulSoup usage_str = """ from test_entry import TestEntry ===================================== from write_excel import ExcelWriter 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: 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.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): def load_file(self, fname): self.contents = "" """ Load xml file """ with open(fname, "r", encoding="utf8") as f: with open(fname, "r", encoding="utf8") as robot_file: self.contents = f.read() self.robot_file_contents = robot_file.read() if self.contents == "": if self.robot_file_contents == "": print("Empty file {}".format(fname)) print("Empty file {}".format(fname)) exit(-1) sys.exit(-1) def run_parser(self): 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 information suite = soup.find("suite") suite = soup.find("suite") path = suite["source"] path = suite["source"] # TODO This might be an issue later on. In Unix-style paths the separator is a forward slash parts = path.split("\\") parts = path.split("\\") # Extract info for test entries # Extract info for test entries self.api = parts[len(parts) - 2] self.api = parts[len(parts) - 2] self.robot_file = parts[len(parts) - 1] self.robot_file_contents = parts[len(parts) - 1] # Tests # Tests tests = soup.find_all("test") tests = soup.find_all("test") Loading @@ -54,10 +57,10 @@ class TestOutputParser: self.test_entries.append(self.create_test_entry(test)) self.test_entries.append(self.create_test_entry(test)) # Write tests # Write tests ew = ExcelWriter() excel_writer = ExcelWriter(self.output_file) for entry in self.test_entries: for entry in self.test_entries: ew.write_test_entry(entry) excel_writer.write_test_entry(entry) ew.save() excel_writer.save() def create_test_entry(self, xml_obj): def create_test_entry(self, xml_obj): """ """ Loading @@ -66,44 +69,28 @@ class TestOutputParser: """ """ # retrieve ID and name # retrieve ID and name id_raw = xml_obj.find("doc", recursive=False).contents id_raw = xml_obj.find("doc", recursive=False).contents mg = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) match_group = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) test_id = mg.group(1) test_id = match_group.group(1) name = xml_obj["name"] name = xml_obj["name"] #retrieve status and error message (if FAIL) #retrieve status and error message (if FAIL) statusObj = xml_obj.find("status", recursive=False) status_obj = xml_obj.find("status", recursive=False) cts = statusObj.contents cts = status_obj.contents error_msg = cts[0] if len(cts) > 0 else "" error_msg = cts[0] if len(cts) > 0 else "" result = statusObj["status"] result = status_obj["status"] return TestEntry(test_id, name, result, error_msg, self.api, self.robot_file) return TestEntry(test_id, name, (result, error_msg), (self.api, self.robot_file_contents)) def display_usage(): print(usage_str) if __name__ == "__main__": if __name__ == "__main__": usage_str = """ parser = argparse.ArgumentParser(description='Robot Test Reporter written in Python.\n' ===================================== 'Produces an xlsx file from a robot XML ' Robot Test Reporter written in Python 'output file.\n' ===================================== 'The command outputs to a new xlslx file if it ' 'does not exist, or appends to an existing one.') Usage parser.add_argument('input_file', help='XML file generated by Robot') parser.add_argument('-o', dest='output_file', default='testResults.xlsx', 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)') help='output file name (default: testResults.xlsx)') args = parser.parse_args() 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 Original line 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 Original line 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 Original line Diff line number Diff line *.xlsx __pycache__/ .vscode/ No newline at end of file
parseTestResults.pydeleted 100644 → 0 +0 −88 Original line number Original line 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 Original line Diff line number Diff line from bs4 import BeautifulSoup """ from sys import argv Tool entry point from testEntry import TestEntry """ from writeExcel import ExcelWriter import sys import re import re import argparse import argparse from bs4 import BeautifulSoup usage_str = """ from test_entry import TestEntry ===================================== from write_excel import ExcelWriter 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: 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.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): def load_file(self, fname): self.contents = "" """ Load xml file """ with open(fname, "r", encoding="utf8") as f: with open(fname, "r", encoding="utf8") as robot_file: self.contents = f.read() self.robot_file_contents = robot_file.read() if self.contents == "": if self.robot_file_contents == "": print("Empty file {}".format(fname)) print("Empty file {}".format(fname)) exit(-1) sys.exit(-1) def run_parser(self): 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 information suite = soup.find("suite") suite = soup.find("suite") path = suite["source"] path = suite["source"] # TODO This might be an issue later on. In Unix-style paths the separator is a forward slash parts = path.split("\\") parts = path.split("\\") # Extract info for test entries # Extract info for test entries self.api = parts[len(parts) - 2] self.api = parts[len(parts) - 2] self.robot_file = parts[len(parts) - 1] self.robot_file_contents = parts[len(parts) - 1] # Tests # Tests tests = soup.find_all("test") tests = soup.find_all("test") Loading @@ -54,10 +57,10 @@ class TestOutputParser: self.test_entries.append(self.create_test_entry(test)) self.test_entries.append(self.create_test_entry(test)) # Write tests # Write tests ew = ExcelWriter() excel_writer = ExcelWriter(self.output_file) for entry in self.test_entries: for entry in self.test_entries: ew.write_test_entry(entry) excel_writer.write_test_entry(entry) ew.save() excel_writer.save() def create_test_entry(self, xml_obj): def create_test_entry(self, xml_obj): """ """ Loading @@ -66,44 +69,28 @@ class TestOutputParser: """ """ # retrieve ID and name # retrieve ID and name id_raw = xml_obj.find("doc", recursive=False).contents id_raw = xml_obj.find("doc", recursive=False).contents mg = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) match_group = re.search(r"Test ID: ([0-9\.]*)$", id_raw[0].string, re.MULTILINE) test_id = mg.group(1) test_id = match_group.group(1) name = xml_obj["name"] name = xml_obj["name"] #retrieve status and error message (if FAIL) #retrieve status and error message (if FAIL) statusObj = xml_obj.find("status", recursive=False) status_obj = xml_obj.find("status", recursive=False) cts = statusObj.contents cts = status_obj.contents error_msg = cts[0] if len(cts) > 0 else "" error_msg = cts[0] if len(cts) > 0 else "" result = statusObj["status"] result = status_obj["status"] return TestEntry(test_id, name, result, error_msg, self.api, self.robot_file) return TestEntry(test_id, name, (result, error_msg), (self.api, self.robot_file_contents)) def display_usage(): print(usage_str) if __name__ == "__main__": if __name__ == "__main__": usage_str = """ parser = argparse.ArgumentParser(description='Robot Test Reporter written in Python.\n' ===================================== 'Produces an xlsx file from a robot XML ' Robot Test Reporter written in Python 'output file.\n' ===================================== 'The command outputs to a new xlslx file if it ' 'does not exist, or appends to an existing one.') Usage parser.add_argument('input_file', help='XML file generated by Robot') parser.add_argument('-o', dest='output_file', default='testResults.xlsx', 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)') help='output file name (default: testResults.xlsx)') args = parser.parse_args() 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 Original line 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 Original line 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]