def test_junit_hex_escape_support(self): reprstring = hex_escape_str(b'\x00\x00\x00\x00\x00\x00\x01\xc8') str_should_be = '<testsuite failures="1" tests="1" errors="0" skipped="0">\n\ <testcase classname="test-case-A1" name="unknown" time="20">\n\ <failure message="' + reprstring + '"></failure>\n\ </testcase>\n\ </testsuite>' results = ResultList() results.append( Result({ "testcase": "test-case-A1", "verdict": "FAIL", "reason": b'\x00\x00\x00\x00\x00\x00\x01\xc8', "duration": 20 })) junit = ReportJunit(results) str_report = junit.to_string() xml_report = ET.fromstring(str_report) shouldbe_report = ET.fromstring(str_should_be) self.assertDictEqual(xml_report.attrib, shouldbe_report.attrib) reported_tc = xml_report.find("testcase") failure_reason = reported_tc.find("failure") required_tc = shouldbe_report.find("testcase") required_reason = required_tc.find("failure") self.assertTrue(required_reason.attrib["message"] == failure_reason.attrib["message"])
def generate(self, *args, **kwargs): """ Generates and prints the console report, which consists of a table of test cases ran as well as a summary table with passrate, number of test cases and statistics on passed/failed/inconclusive/skipped cases. :param args: arguments, not used :param kwargs: keyword arguments, not used :return: Nothing """ # Generate TC result table table = PrettyTable([ "Testcase", "Verdict", "Fail Reason", "Skip Reason", "platforms", "duration", "Retried" ]) for result in self.results: table.add_row([ result.get_tc_name(), result.get_verdict(), hex_escape_str(result.fail_reason)[:60], str(result.skip_reason) if result.skipped() else "", result.get_dut_models(), str(result.duration), "Yes" if result.retries_left != 0 else "No" ]) # Print to console print(table) # pylint: disable=superfluous-parens # Generate Summary table table = PrettyTable(['Summary', '']) final_verdict = "FAIL" if self.summary["fail"] == 0 and self.summary["inconclusive"] == 0: final_verdict = "PASS" elif self.results.clean_inconcs() and not self.results.clean_fails(): final_verdict = "INCONCLUSIVE" elif self.summary["fail"] + self.summary[ "inconclusive"] == self.summary["retries"]: final_verdict = "PASS" table.add_row(["Final Verdict", final_verdict]) table.add_row(["count", str(self.summary["count"])]) table.add_row(["passrate", self.results.pass_rate()]) table.add_row([ "passrate excluding retries", self.results.pass_rate(include_retries=False) ]) if self.summary["pass"] > 0: table.add_row(["pass", str(self.summary["pass"])]) if self.summary["fail"] > 0: table.add_row(["fail", str(self.summary["fail"])]) if self.summary["skip"] > 0: table.add_row(["skip", str(self.summary["skip"])]) if self.summary["inconclusive"] > 0: table.add_row(["inconclusive", str(self.summary["inconclusive"])]) table.add_row( ["Duration", self.duration_to_string(self.summary["duration"])]) # Print to console print(table) # pylint: disable=superfluous-parens
def __generate(results): """ Static method which generates the Junit xml string from results :param results: Results as ResultList object. :return: Junit xml format string. """ doc, tag, text = Doc().tagtext() # Counters for testsuite tag info count = 0 fails = 0 errors = 0 skips = 0 for result in results: # Loop through all results and count the ones that were not later retried. if result.passed() is False: if result.retries_left > 0: # This will appear in the list again, move on continue count += 1 if result.passed(): # Passed, no need to increment anything else continue elif result.skipped(): skips += 1 elif result.was_inconclusive(): errors += 1 else: fails += 1 with tag('testsuite', tests=str(count), failures=str(fails), errors=str(errors), skipped=str(skips)): for result in results: if result.passed() is False and result.retries_left > 0: continue class_name = result.get_tc_name() models = result.get_dut_models() if models: class_name = class_name + "." + models name = result.get_toolchain() with tag('testcase', classname=class_name, name=name, time=result.get_duration(seconds=True)): if result.stdout: with tag('system-out'): text(result.stdout) if result.passed(): continue elif result.skipped(): with tag('skipped'): text(result.skip_reason) elif result.was_inconclusive(): with tag('error', message=hex_escape_str(result.fail_reason)): text(result.stderr) else: with tag('failure', message=hex_escape_str(result.fail_reason)): text(result.stderr) return indent(doc.getvalue(), indentation=' ' * 4)
def _create(self, title, heads, refresh=None, path_start=None): """ Internal create method, uses yattag to generate a html document with result data. :param title: Title of report :param heads: Headers for report :param refresh: If set to True, adds a HTTP-EQUIV="refresh" to the report :param path_start: path to file where this is report is to be stored. :return: yattag document. """ # TODO: Refactor to make less complex doc, tag, text = Doc().tagtext() doc.asis('<!DOCTYPE html>') heads["Date"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") heads["Pass rate"] = self.results.pass_rate() heads["Pass rate excluding retries"] = self.results.pass_rate(include_retries=False) with tag('html'): with tag('head'): doc.asis(self.head) if refresh: doc.asis('<META HTTP-EQUIV="refresh" CONTENT="' + str(refresh) + '">') with tag('body', id='body'): with tag('h1'): text(title) with tag('table'): for head in heads: with tag('tr'): with tag('th', width="100px"): text(head) with tag('td'): text(heads[head]) with tag('tr'): with tag('th'): text('Executed') with tag('td'): text(str(self.summary["count"])) with tag('tr'): with tag('th'): text('Pass:'******'td'): text(str(self.summary["pass"])) with tag('tr'): with tag('th'): text('Fails:') with tag('td'): text(str(self.summary["fail"])) with tag('tr'): with tag('th'): text('inconclusive:') with tag('td'): text(str(self.summary["inconclusive"])) with tag('tr'): with tag('th'): text('Skip:') with tag('td'): text(str(self.summary["skip"])) with tag('tr'): with tag('th'): text('Duration:') with tag('td'): text(self.duration_to_string(self.summary["duration"])) with tag('tr'): with tag('th'): text('{} version:'.format(get_fw_name())) with tag('td'): text(get_fw_version()) with tag('table', style='border-collapse: collapse;'): with tag('tr'): with tag('th'): text("Test Case") with tag('th'): text("Verdict") with tag('th'): text("Fail Reason") with tag('th'): text("Skip Reason") with tag('th'): text("Retried") with tag('th'): text("Duration") for result in self.results: if result.success: klass = 'item_pass' elif result.inconclusive: klass = 'item_inconc' else: klass = 'item_fail' with tag('tr', klass='item %s' % klass, onclick='showhide(this)'): with tag('td', width="200px"): text(result.get_tc_name()) with tag('td', width="100px"): if result.success: color = 'green' elif result.failure: color = 'red' else: color = 'black' with tag('font', color=color): text(result.get_verdict()) with tag('td', width="350px"): text(hex_escape_str(result.fail_reason)) with tag('td', width="300px"): text(result.skip_reason if result.skipped() else "") with tag('td', width="50px"): text("Yes" if result.retries_left != 0 else "No") with tag('td', width="100px"): text(str(result.duration)) with tag('tr', klass='info hidden'): with tag('td', colspan="5"): if hasattr(result, 'tc_git_info') and \ result.tc_git_info and \ "scm_link" in result.tc_git_info: # add tc git info only when available link = result.tc_git_info['scm_link'] with tag('a', href=link): text(link) doc.stag('br') for fil in result.logfiles: filepath = os.path.relpath(fil, path_start) with tag('a', href=filepath): text(filepath) doc.stag('br') return doc.getvalue()
def test_hex_escape_tester(self): failing_message = "\x00\x00\x00\x00\x00\x00\x01\xc8" success_message = "\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xc8" converted = tools.hex_escape_str(failing_message) self.assertEqual(converted, success_message)