From 5342dfa4a074f7d6e9b814796164bfe53b3ae38e Mon Sep 17 00:00:00 2001 From: Lucas Ribeiro Date: Thu, 17 Nov 2016 21:46:38 -0200 Subject: [PATCH 1/5] decouple templates from code --- HTMLTestRunner.py | 435 ++++--------------------- templates/heading.html | 5 + templates/heading_attribute.html | 1 + templates/report.html | 114 +++++++ templates/report_class.html | 11 + templates/report_table.html | 35 ++ templates/report_test_no_output.html | 6 + templates/report_test_with_output.html | 22 ++ templates/stylesheet.html | 147 +++++++++ 9 files changed, 407 insertions(+), 369 deletions(-) create mode 100644 templates/heading.html create mode 100644 templates/heading_attribute.html create mode 100644 templates/report.html create mode 100644 templates/report_class.html create mode 100644 templates/report_table.html create mode 100644 templates/report_test_no_output.html create mode 100644 templates/report_test_with_output.html create mode 100644 templates/stylesheet.html diff --git a/HTMLTestRunner.py b/HTMLTestRunner.py index 0815568..da30f64 100644 --- a/HTMLTestRunner.py +++ b/HTMLTestRunner.py @@ -1,5 +1,5 @@ -import datetime import StringIO +import datetime import sys import unittest from xml.sax import saxutils @@ -12,17 +12,17 @@ # TODO: simplify javascript using ,ore than 1 class in the class attribute? -# ---------------------------------------------------------------------------- # -# The redirectors below are used to capture output during testing. Output -# sent to sys.stdout and sys.stderr are automatically captured. However -# in some cases sys.stdout is already cached before HTMLTestRunner is -# invoked (e.g. calling logging.basicConfig). In order to capture those -# output, use the redirectors for the cached stream. -# +# ------------------------------------------------------------------- # +# The redirectors below are used to capture output during testing. +# Output sent to sys.stdout and sys.stderr are automatically captured. +# However in some cases sys.stdout is already cached before +# HTMLTestRunner is invoked (e.g. calling logging.basicConfig). +# In order to capture those output, use the redirectors for the cached +# stream. # e.g. # >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector) # >>> -# ---------------------------------------------------------------------------- # +# ------------------------------------------------------------------- # def to_unicode(s): @@ -101,371 +101,67 @@ class TemplateMixin(object): 3: 'SKIP', } - DEFAULT_TITLE = 'Unit Test Report' + DEFAULT_TITLE = 'Test Report' DEFAULT_DESCRIPTION = '' -# ---------------------------------------------------------------------------- # -# HTML Template -# ---------------------------------------------------------------------------- # - # variables: (title, generator, stylesheet, heading, report, ending) - HTML_TMPL = r""" - - - - - %(title)s - - - %(stylesheet)s - - - - -%(heading)s -%(report)s -%(ending)s - - -""" - -# ---------------------------------------------------------------------------- # -# Stylesheet -# ---------------------------------------------------------------------------- # -# alternatively use a for external style sheet, e.g. -# - STYLESHEET_TMPL = r""" -""" - -# ---------------------------------------------------------------------------- # -# Heading -# ---------------------------------------------------------------------------- # + # variables: (title, generator, stylesheet, heading, report, ending) + HTML_TEMPLATE = open('templates/report.html', 'r').read().encode('utf-8') + + # ------------------------------------------------------------------- # + # Stylesheet + # ------------------------------------------------------------------- # + # alternatively use a for external style sheet, e.g. + # + STYLESHEET_TEMPLATE = open('templates/stylesheet.html', 'r').read() \ + .encode('utf-8') + + # ------------------------------------------------------------------- # + # Heading + # ------------------------------------------------------------------- # # variables: (title, parameters, description) - HEADING_TMPL = r""" -
-

%(title)s

- %(parameters)s -

%(description)s

-
""" + HEADING_TEMPLATE = open('templates/heading.html', 'r').read() \ + .encode('utf-8') # variables: (name, value) - HEADING_ATTRIBUTE_TMPL = r""" -

%(name)s: %(value)s

""" + HEADING_ATTRIBUTE_TEMPLATE = open('templates/heading_attribute.html', 'r')\ + .read().encode('utf-8') - -# ---------------------------------------------------------------------------- # -# Report -# ---------------------------------------------------------------------------- # + # ------------------------------------------------------------------- # + # Report + # ------------------------------------------------------------------- # # variables: (test_list, count, Pass, fail, error, skip) - REPORT_TMPL = r""" -

Show -Summary -Failed -Skipped -All -

- -------- - - - - - - - - - -%(test_list)s - - - - - - - - - -
Test Group/Test caseCountPassFailErrorSkipView
Total%(count)s%(Pass)s%(fail)s%(error)s%(skip)s 
""" + REPORT__TABLE_TEMPLATE = open('templates/report_table.html', 'r') \ + .read().encode('utf-8') # variables: (style, desc, count, Pass, fail, error, cid) - REPORT_CLASS_TMPL = r""" - - %(desc)s - %(count)s - %(Pass)s - %(fail)s - %(error)s - %(skip)s - - Detail - -""" + REPORT_CLASS_TEMPLATE = open('templates/report_class.html', 'r').read()\ + .encode('utf-8') # variables: (tid, Class, style, desc, status) - REPORT_TEST_WITH_OUTPUT_TMPL = r""" - -
%(desc)s
- - - - - %(status)s - - - - -""" + REPORT_TEST_WITH_OUTPUT_TMPL = \ + open('templates/report_test_with_output.html', 'r').read()\ + .encode('utf-8') # variables: (tid, Class, style, desc, status) - REPORT_TEST_NO_OUTPUT_TMPL = r""" - - -
%(desc)s
- - %(status)s -""" + REPORT_TEST_NO_OUTPUT_TEMPLATE = \ + open('templates/report_test_no_output.html', 'r').read()\ + .encode('utf-8') # variables: (id, output) - REPORT_TEST_OUTPUT_TMPL = r"""%(id)s: %(output)s""" - + REPORT_TEST_OUTPUT_TEMPLATE = r"""%(id)s: %(output)s""" -# ---------------------------------------------------------------------------- # -# ENDING -# ---------------------------------------------------------------------------- # - ENDING_TMPL = r"""
 
""" + # ------------------------------------------------------------------- # + # ENDING + # ------------------------------------------------------------------- # + ENDING_TEMPLATE = r"""
 
""" # -------------------- The end of the Template class ------------------- - TestResult = unittest.TestResult @@ -589,7 +285,7 @@ def sort_result(result_list): rmap[cls] = [] classes.append(cls) rmap[cls].append((n, t, o, e)) - r = [(cls, rmap[cls]) for cls in classes] + r = [(clazz, rmap[clazz]) for clazz in classes] return r @@ -616,8 +312,8 @@ def run(self, test): test(result) self.stopTime = datetime.datetime.now() self.generate_report(result) - print >> sys.stderr, '\nTime Elapsed: %s' % \ - (self.stopTime - self.startTime) + total_time = self.stopTime - self.startTime + print >> sys.stderr, '\nTime Elapsed: %s' % total_time return result def get_report_attributes(self, result): @@ -653,7 +349,7 @@ def generate_report(self, result): heading = self._generate_heading(report_attrs) report = self._generate_report(result) ending = self._generate_ending() - output = self.HTML_TMPL % dict( + output = self.HTML_TEMPLATE % dict( title=saxutils.escape(self.title), generator=generator, stylesheet=stylesheet, @@ -664,17 +360,17 @@ def generate_report(self, result): self.stream.write(output.encode('utf8')) def _generate_stylesheet(self): - return self.STYLESHEET_TMPL + return self.STYLESHEET_TEMPLATE def _generate_heading(self, report_attrs): attrs_list = [] for attr_name, attr_value in report_attrs: - attr_line = self.HEADING_ATTRIBUTE_TMPL % dict( + attr_line = self.HEADING_ATTRIBUTE_TEMPLATE % dict( name=saxutils.escape(attr_name), value=saxutils.escape(attr_value), ) attrs_list.append(attr_line) - heading = self.HEADING_TMPL % dict( + heading = self.HEADING_TEMPLATE % dict( title=saxutils.escape(self.title), parameters=''.join(attrs_list), description=saxutils.escape(self.description), @@ -696,9 +392,9 @@ def _generate_report(self, result): ne += 1 elif n == 3: ns += 1 - # else: - # # ne += 1 - # print 'TESTING' + # else: + # # ne += 1 + # print 'TESTING' # format class description if cls.__module__ == "__main__": @@ -713,7 +409,7 @@ def _generate_report(self, result): or ns > 0 and 'skipClass' \ or 'passClass' - row = self.REPORT_CLASS_TMPL % dict( + row = self.REPORT_CLASS_TEMPLATE % dict( style=s, desc=desc, count=np + nf + ne + ns, @@ -731,7 +427,7 @@ def _generate_report(self, result): + result.failure_count \ + result.error_count \ + result.skip_count - report = self.REPORT_TMPL % dict( + report = self.REPORT__TABLE_TEMPLATE % dict( test_list=''.join(rows), count=str(result_sum), Pass=str(result.success_count), @@ -744,7 +440,8 @@ def _generate_report(self, result): def _generate_report_test(self, rows, class_id, test_id, n, t, output, e): # e.g. 'pt1.1', 'ft1.1', etc has_output = bool(output or e) - test_id = (n == 0 and 'p' or 'f') + 't%s.%s' % (class_id+1, test_id+1) + test_id = (n == 0 and 'p' or 'f') + 't%s.%s' \ + % (class_id + 1, test_id + 1) name = t.id().split('.')[-1] doc = t.shortDescription() or "" desc = doc and ('%s: %s' % (name, doc)) or name @@ -753,7 +450,7 @@ def _generate_report_test(self, rows, class_id, test_id, n, t, output, e): if has_output: tmpl = self.REPORT_TEST_WITH_OUTPUT_TMPL else: - tmpl = self.REPORT_TEST_NO_OUTPUT_TMPL + tmpl = self.REPORT_TEST_NO_OUTPUT_TEMPLATE # o and e should be byte string because # they are collected from stdout and stderr? if isinstance(output, str): @@ -771,7 +468,7 @@ def _generate_report_test(self, rows, class_id, test_id, n, t, output, e): else: ue = e - script = self.REPORT_TEST_OUTPUT_TMPL % dict( + script = self.REPORT_TEST_OUTPUT_TEMPLATE % dict( id=test_id, output=saxutils.escape(uo + ue), ) @@ -789,7 +486,7 @@ def _generate_report_test(self, rows, class_id, test_id, n, t, output, e): return def _generate_ending(self): - return self.ENDING_TMPL + return self.ENDING_TEMPLATE ############################################################################## diff --git a/templates/heading.html b/templates/heading.html new file mode 100644 index 0000000..77608f6 --- /dev/null +++ b/templates/heading.html @@ -0,0 +1,5 @@ +
+

%(title)s

+ %(parameters)s +

%(description)s

+
diff --git a/templates/heading_attribute.html b/templates/heading_attribute.html new file mode 100644 index 0000000..3fbfe77 --- /dev/null +++ b/templates/heading_attribute.html @@ -0,0 +1 @@ +

%(name)s: %(value)s

diff --git a/templates/report.html b/templates/report.html new file mode 100644 index 0000000..ad9aea4 --- /dev/null +++ b/templates/report.html @@ -0,0 +1,114 @@ + + + + + %(title)s + + + %(stylesheet)s + + + + +%(heading)s +%(report)s +%(ending)s + + + \ No newline at end of file diff --git a/templates/report_class.html b/templates/report_class.html new file mode 100644 index 0000000..93db0c2 --- /dev/null +++ b/templates/report_class.html @@ -0,0 +1,11 @@ + + %(desc)s + %(count)s + %(Pass)s + %(fail)s + %(error)s + %(skip)s + + Detail + + diff --git a/templates/report_table.html b/templates/report_table.html new file mode 100644 index 0000000..93a7675 --- /dev/null +++ b/templates/report_table.html @@ -0,0 +1,35 @@ +

Show + Summary + Failed + Skipped + All +

+ + + + + + + + + + + + + + + + + + + %(test_list)s + + + + + + + + + +
Test Group/Test caseCountPassFailErrorSkipView
Total%(count)s%(Pass)s%(fail)s%(error)s%(skip)s 
diff --git a/templates/report_test_no_output.html b/templates/report_test_no_output.html new file mode 100644 index 0000000..488ebff --- /dev/null +++ b/templates/report_test_no_output.html @@ -0,0 +1,6 @@ + + +
%(desc)s
+ + %(status)s + diff --git a/templates/report_test_with_output.html b/templates/report_test_with_output.html new file mode 100644 index 0000000..ec35ec0 --- /dev/null +++ b/templates/report_test_with_output.html @@ -0,0 +1,22 @@ + +
%(desc)s
+ + + + + %(status)s + + + + + diff --git a/templates/stylesheet.html b/templates/stylesheet.html new file mode 100644 index 0000000..a703933 --- /dev/null +++ b/templates/stylesheet.html @@ -0,0 +1,147 @@ + From fef69ee6dfa2051954d94bc3f2e81deb4cad4fe8 Mon Sep 17 00:00:00 2001 From: Lucas Ribeiro Date: Thu, 24 Nov 2016 22:52:41 -0200 Subject: [PATCH 2/5] Update __version__ to 2.0.0 --- HTMLTestRunner.py | 2 +- sample_test_report.html | 465 ---------------------------------------- 2 files changed, 1 insertion(+), 466 deletions(-) delete mode 100644 sample_test_report.html diff --git a/HTMLTestRunner.py b/HTMLTestRunner.py index da30f64..1bef060 100644 --- a/HTMLTestRunner.py +++ b/HTMLTestRunner.py @@ -5,7 +5,7 @@ from xml.sax import saxutils __author__ = "Wai Yip Tung" -__version__ = "0.8.3" +__version__ = "2.0.0" # TODO: color stderr diff --git a/sample_test_report.html b/sample_test_report.html deleted file mode 100644 index 4c3334c..0000000 --- a/sample_test_report.html +++ /dev/null @@ -1,465 +0,0 @@ - - - - - - Unit Test Report - - - - - - - - - -
-

Unit Test Report

- -

Start Time: 2015-11-02 13:24:10

-

Duration: 0:00:00.001000

-

Status: Pass 1, Skip 3, Failure 1, Error 1

-

-
- -

Show -Summary -Failed -Skipped -All -

- -------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Test Group/Test caseCountPassFailErrorSkipView
ErrorTestCase10010 - Detail -
test_error: A test that raise an exception
- - - - ERROR - - - -
FailTestCase10100 - Detail -
test_fail: A test that fails
- - - - FAIL - - - -
PassTestCase11000 - Detail -
-
test_pass: A test that passes
-
PASS
SkipBeforeTestMethodTestCase10001 - Detail -
test_skip_before_test_method
- - - - SKIP - - - -
SkipClassTestCase10001 - Detail -
test_skip_class
- - - - SKIP - - - -
SkipInsideTestMethodTestCase10001 - Detail -
test_skip_inside_test_method
- - - - SKIP - - - -
Total61113 
-
 
- - - \ No newline at end of file From e7d104bde64d8d6a059c1fdf638f02f6f737b147 Mon Sep 17 00:00:00 2001 From: Lucas Ribeiro Date: Thu, 24 Nov 2016 22:53:19 -0200 Subject: [PATCH 3/5] Update templates indentation --- templates/report.html | 181 ++++++++-------- templates/report_class.html | 2 +- templates/report_table.html | 2 +- templates/report_test_with_output.html | 26 +-- templates/stylesheet.html | 289 ++++++++++++------------- 5 files changed, 248 insertions(+), 252 deletions(-) diff --git a/templates/report.html b/templates/report.html index ad9aea4..3efa7f1 100644 --- a/templates/report.html +++ b/templates/report.html @@ -1,7 +1,6 @@ - - + + %(title)s @@ -9,106 +8,106 @@ %(stylesheet)s - + /* obsoleted by detail in
+ function showOutput(id, name) { + var w = window.open("", //url + name, + "resizable,scrollbars,status,width=800,height=450"); + d = w.document; + d.write("
");
+            d.write(html_escape(output_list[id]));
+            d.write("\n");
+            d.write("close\n");
+            d.write("
\n"); + d.close(); + } + */ + --> + -%(heading)s -%(report)s -%(ending)s + %(heading)s + %(report)s + %(ending)s - \ No newline at end of file + diff --git a/templates/report_class.html b/templates/report_class.html index 93db0c2..0cd679e 100644 --- a/templates/report_class.html +++ b/templates/report_class.html @@ -6,6 +6,6 @@ %(error)s %(skip)s - Detail + Detail diff --git a/templates/report_table.html b/templates/report_table.html index 93a7675..35d8b95 100644 --- a/templates/report_table.html +++ b/templates/report_table.html @@ -30,6 +30,6 @@ %(fail)s %(error)s %(skip)s -   +   diff --git a/templates/report_test_with_output.html b/templates/report_test_with_output.html index ec35ec0..fb54a79 100644 --- a/templates/report_test_with_output.html +++ b/templates/report_test_with_output.html @@ -1,22 +1,20 @@ -
%(desc)s
+ +
%(desc)s
+ - - - %(status)s + + %(status)s -