Skip to content

Commit 304f9b0

Browse files
committed
Improve HTML output
Signed-off-by: Conor MacBride <[email protected]>
1 parent db741b0 commit 304f9b0

File tree

1 file changed

+95
-10
lines changed

1 file changed

+95
-10
lines changed

pytest_mpl/plugin.py

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,20 @@
5959
table, th, td {
6060
border: 1px solid black;
6161
}
62+
.summary > div {
63+
padding: 0.5em;
64+
}
65+
tr.passed .status, .rms.passed, .hashes.passed {
66+
color: green;
67+
}
68+
tr.failed .status, .rms.failed, .hashes.failed {
69+
color: red;
70+
}
6271
</style>
6372
</head>
6473
<body>
6574
<h2>Image test comparison</h2>
75+
%summary%
6676
<table>
6777
<tr>
6878
<th>Test Name</th>
@@ -301,6 +311,7 @@ def __init__(self,
301311
# We need global state to store all the hashes generated over the run
302312
self._generated_hash_library = {}
303313
self._test_results = {}
314+
self._test_stats = None
304315

305316
def get_compare(self, item):
306317
"""
@@ -701,22 +712,94 @@ def item_function_wrapper(*args, **kwargs):
701712
else:
702713
item.obj = item_function_wrapper
703714

704-
def generate_summary_html(self, dir_list):
715+
def generate_stats(self):
716+
"""
717+
Generate a dictionary of summary statistics.
718+
"""
719+
stats = {'passed': 0, 'failed': 0, 'passed_baseline': 0, 'failed_baseline': 0, 'skipped': 0}
720+
for test in self._test_results.values():
721+
if test['status'] == 'passed':
722+
stats['passed'] += 1
723+
if test['rms'] is not None:
724+
stats['failed_baseline'] += 1
725+
elif test['status'] == 'failed':
726+
stats['failed'] += 1
727+
if test['rms'] is None:
728+
stats['passed_baseline'] += 1
729+
elif test['status'] == 'skipped':
730+
stats['skipped'] += 1
731+
else:
732+
raise ValueError(f"Unknown test status '{test['status']}'.")
733+
self._test_stats = stats
734+
735+
def generate_summary_html(self):
705736
"""
706737
Generate a simple HTML table of the failed test results
707738
"""
708739
html_file = self.results_dir / 'fig_comparison.html'
709740
with open(html_file, 'w') as f:
710-
f.write(HTML_INTRO)
711741

712-
for directory in dir_list:
713-
test_name = directory.parts[-1]
714-
test_result = 'passed' if self._test_results[test_name] is True else 'failed'
715-
f.write('<tr>'
716-
f'<td>{test_name} ({test_result})\n'
717-
f'<td><img src="{directory / "baseline.png"}"></td>\n'
718-
f'<td><img src="{directory / "result-failed-diff.png"}"></td>\n'
719-
f'<td><img src="{directory / "result.png"}"></td>\n'
742+
passed = f"{self._test_stats['passed']} passed"
743+
if self._test_stats['failed_baseline'] > 0:
744+
passed += (" hash comparison, although "
745+
f"{self._test_stats['failed_baseline']} "
746+
"of those have a different baseline image")
747+
748+
failed = f"{self._test_stats['failed']} failed"
749+
if self._test_stats['passed_baseline'] > 0:
750+
failed += (" hash comparison, although "
751+
f"{self._test_stats['passed_baseline']} "
752+
"of those have a matching baseline image")
753+
754+
f.write(HTML_INTRO.replace('%summary%', f'<p>{passed}.</p><p>{failed}.</p>'))
755+
756+
for test_name in sorted(self._test_results.keys()):
757+
summary = self._test_results[test_name]
758+
759+
if summary['rms'] is None and summary['tolerance'] is not None:
760+
rms = (f'<div class="rms passed">\n'
761+
f' <strong>RMS:</strong> '
762+
f' &lt; <span class="tolerance">{summary["tolerance"]}</span>\n'
763+
f'</div>')
764+
elif summary['rms'] is not None:
765+
rms = (f'<div class="rms failed">\n'
766+
f' <strong>RMS:</strong> '
767+
f' <span class="rms">{summary["rms"]}</span>\n'
768+
f'</div>')
769+
else:
770+
rms = ''
771+
772+
hashes = ''
773+
if summary['baseline_hash'] is not None:
774+
hashes += (f' <div class="baseline">Baseline: '
775+
f'{summary["baseline_hash"]}</div>\n')
776+
if summary['result_hash'] is not None:
777+
hashes += (f' <div class="result">Result: '
778+
f'{summary["result_hash"]}</div>\n')
779+
if len(hashes) > 0:
780+
if summary["baseline_hash"] == summary["result_hash"]:
781+
hash_result = 'passed'
782+
else:
783+
hash_result = 'failed'
784+
hashes = f'<div class="hashes {hash_result}">\n{hashes}</div>'
785+
786+
images = {}
787+
for image_type in ['baseline_image', 'diff_image', 'result_image']:
788+
if summary[image_type] is not None:
789+
images[image_type] = f'<img src="{summary[image_type]}" />'
790+
else:
791+
images[image_type] = ''
792+
793+
f.write(f'<tr class="{summary["status"]}">\n'
794+
' <td>\n'
795+
' <div class="summary">\n'
796+
f' <div class="test-name">{test_name}</div>\n'
797+
f' <div class="status">{summary["status"]}</div>\n'
798+
f' {rms}{hashes}\n'
799+
' </td>\n'
800+
f' <td>{images["baseline_image"]}</td>\n'
801+
f' <td>{images["diff_image"]}</td>\n'
802+
f' <td>{images["result_image"]}</td>\n'
720803
'</tr>\n\n')
721804

722805
f.write('</table>\n')
@@ -757,6 +840,8 @@ def pytest_unconfigure(self, config):
757840
if self._test_results[test_name][image_type] == '%EXISTS%':
758841
self._test_results[test_name][image_type] = str(directory / filename)
759842

843+
self.generate_stats()
844+
760845
if 'json' in self.generate_summary:
761846
summary = self.generate_summary_json()
762847
print(f"A JSON report can be found at: {summary}")

0 commit comments

Comments
 (0)