-
Notifications
You must be signed in to change notification settings - Fork 315
Check graphic hash #2161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check graphic hash #2161
Changes from 26 commits
e4951c8
780276a
baae9d3
a574517
1563c66
f799dd4
65fd0d5
19c33ae
bdac68c
a7de297
14a76b7
e6075ab
c137581
e83d0ab
064a3b4
690a766
7cba57a
67a8be9
908e8e0
e825ab8
fe01819
5c907d8
5a83256
cdcb22c
1a2eb91
eb2e7b7
4e05eb0
77d9f86
3f89ab2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,13 +34,16 @@ | |
| from six.moves import (filter, input, map, range, zip) # noqa | ||
| import six | ||
|
|
||
| import codecs | ||
| import collections | ||
| import contextlib | ||
| import difflib | ||
| import filecmp | ||
| import functools | ||
| import gzip | ||
| import hashlib | ||
| import inspect | ||
| import json | ||
| import io | ||
| import logging | ||
| import os | ||
|
|
@@ -620,16 +623,20 @@ def _unique_id(self): | |
|
|
||
| """ | ||
| # Obtain a consistent ID for the current test. | ||
|
|
||
| # NB. unittest.TestCase.id() returns different values depending on | ||
| # whether the test has been run explicitly, or via test discovery. | ||
| # For example: | ||
| # python tests/test_plot.py => '__main__.TestContourf.test_tx' | ||
| # ird -t => 'iris.tests.test_plot.TestContourf.test_tx' | ||
| bits = self.id().split('.')[-3:] | ||
| bits = self.id().split('.') | ||
| if bits[0] == '__main__': | ||
| file_name = os.path.basename(sys.modules['__main__'].__file__) | ||
| floc = sys.modules['__main__'].__file__ | ||
| path, file_name = os.path.split(os.path.abspath(floc)) | ||
| bits[0] = os.path.splitext(file_name)[0] | ||
| folder, location = os.path.split(path) | ||
| while location != 'iris': | ||
| folder, location = os.path.split(folder) | ||
| bits = [location] + bits | ||
| test_id = '.'.join(bits) | ||
|
|
||
| # Derive the sequential assertion ID within the test | ||
|
|
@@ -652,21 +659,22 @@ def _ensure_folder(self, path): | |
| logger.warning('Creating folder: %s', dir_path) | ||
| os.makedirs(dir_path) | ||
|
|
||
| def check_graphic(self, tol=_DEFAULT_IMAGE_TOLERANCE): | ||
| """Checks the CRC matches for the current matplotlib.pyplot figure, and closes the figure.""" | ||
| def check_graphic(self, tol=None): | ||
| """ | ||
| Checks the CRC matches for the current matplotlib.pyplot figure, | ||
| and closes the figure. | ||
|
|
||
| """ | ||
|
|
||
| unique_id = self._unique_id() | ||
|
|
||
| figure = plt.gcf() | ||
|
|
||
| repo_fname = os.path.join(os.path.dirname(__file__), 'results', 'imagerepo.json') | ||
| with open(repo_fname, 'rb') as fi: | ||
| repo = json.load(codecs.getreader('utf-8')(fi)) | ||
|
|
||
| try: | ||
| expected_fname = os.path.join(os.path.dirname(__file__), | ||
| 'results', 'visual_tests', | ||
| unique_id + '.png') | ||
|
|
||
| if not os.path.isdir(os.path.dirname(expected_fname)): | ||
| os.makedirs(os.path.dirname(expected_fname)) | ||
|
|
||
| #: The path where the images generated by the tests should go. | ||
| image_output_directory = os.path.join(os.path.dirname(__file__), | ||
| 'result_image_comparison') | ||
|
|
@@ -695,18 +703,50 @@ def check_graphic(self, tol=_DEFAULT_IMAGE_TOLERANCE): | |
|
|
||
| figure.savefig(result_fname) | ||
|
|
||
| if not os.path.exists(expected_fname): | ||
| warnings.warn('Created image for test %s' % unique_id) | ||
| # XXX: Deal with a new test result i.e. it's not in the repo | ||
|
|
||
| # hash the created image using sha1 | ||
| with open(result_fname, 'rb') as res_file: | ||
| sha1 = hashlib.sha1(res_file.read()) | ||
|
|
||
| emsg = None | ||
|
|
||
| try: | ||
| uris = repo[unique_id] | ||
| except KeyError: | ||
| # This test is not registered in the image json store, | ||
| # therefore treat it as a *new* test to be registered. | ||
| dname = os.path.join(os.path.dirname(__file__), | ||
| 'results', 'visual_tests') | ||
| expected_fname = os.path.join(dname, unique_id+'.png') | ||
| if not os.path.isdir(dname): | ||
| os.makedirs(dname) | ||
| wmsg = 'Created image for test {}' | ||
| warnings.warn(wmsg.format(unique_id)) | ||
| shutil.copy2(result_fname, expected_fname) | ||
|
|
||
| err = mcompare.compare_images(expected_fname, result_fname, tol=tol) | ||
| else: | ||
| # Cherry-pick the registered expected hashes from the | ||
| # test case uri/s. | ||
| expected = [] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think a list comprehension would be clearer than init + append here. |
||
| for uri in uris: | ||
| ehash = os.path.splitext(os.path.basename(uri))[0] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd still prefer that the url + hash were kept logically separate, and not insist that the filename "is" the hash. |
||
| expected.append(ehash) | ||
|
|
||
| if sha1.hexdigest() not in expected: | ||
| emsg = 'Actual SHA1 {} not in expected {} for test {}.' | ||
| emsg = emsg.format(sha1.hexdigest(), expected, unique_id) | ||
| else: | ||
| # There is no difference between the actual and expected | ||
| # result, so remove the actual result file. | ||
| os.remove(result_fname) | ||
|
|
||
| if _DISPLAY_FIGURES: | ||
| if err: | ||
| print('Image comparison would have failed. Message: %s' % err) | ||
| if emsg is not None: | ||
| print('Image comparison would have failed. ' | ||
| 'Message: %s' % emsg) | ||
| plt.show() | ||
| else: | ||
| assert not err, 'Image comparison failed. Message: %s' % err | ||
| assert not emsg, 'Image comparison failed. Message: %s' % emsg | ||
|
|
||
| finally: | ||
| plt.close() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could make sense to remove the support for the "print-failed-images" key from setup.py.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for now i'm putting this back in; if it is removed then we can discuss removing the functionality too