Skip to content

Commit

Permalink
Save images from image tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dstansby committed May 29, 2018
1 parent dc48228 commit 8aa1e10
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 28 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -75,4 +75,6 @@ $RECYCLE.BIN/
.hypothesis/
.pytest_cache/
sunpydata.sqlite

v/
result_images*
14 changes: 4 additions & 10 deletions sunpy/conftest.py
Expand Up @@ -14,7 +14,7 @@
matplotlib.use('Agg')

from sunpy.tests.hash import HASH_LIBRARY_NAME
from sunpy.tests.helpers import new_hash_library, figure_test_pngfiles
from sunpy.tests.helpers import new_hash_library, test_fig_dir
from sunpy.extern import six

import pytest
Expand Down Expand Up @@ -47,17 +47,11 @@ def pytest_runtest_setup(item):


def pytest_unconfigure(config):
if len(figure_test_pngfiles) > 0:
tempdir = tempfile.mkdtemp(suffix="_figures")

# Rename each PNG with the name of the corresponding test
for test_name in figure_test_pngfiles:
os.rename(figure_test_pngfiles[test_name], os.path.join(tempdir, test_name + '.png'))

if len(new_hash_library) > 0:
# Write the new hash library in JSON
hashfile = os.path.join(tempdir, HASH_LIBRARY_NAME)
hashfile = os.path.join(test_fig_dir, HASH_LIBRARY_NAME)
with open(hashfile, 'w') as outfile:
json.dump(new_hash_library, outfile, sort_keys=True, indent=4, separators=(',', ': '))

print('All test files for figure hashes can be found in {0}'.format(tempdir))
print('All images from image tests can be found in {0}'.format(test_fig_dir))
print("The corresponding hash library is {0}".format(hashfile))
11 changes: 9 additions & 2 deletions sunpy/tests/hash.py
Expand Up @@ -46,11 +46,18 @@ def hash_figure(figure=None, out_stream=None):

figure.savefig(imgdata, format='png')

imgdata.seek(0)
buf = imgdata.read()
out = _hash_file(imgdata)
if out_stream is None:
imgdata.close()
return out


def _hash_file(in_stream):
"""
Hashes an already opened file
"""
in_stream.seek(0)
buf = in_stream.read()
hasher = hashlib.sha256()
hasher.update(buf)
return hasher.hexdigest()
Expand Down
50 changes: 34 additions & 16 deletions sunpy/tests/helpers.py
Expand Up @@ -7,6 +7,7 @@
import tempfile
import platform
import os
import datetime

import pytest
import numpy as np
Expand Down Expand Up @@ -40,9 +41,7 @@
SKIP_ANA = False

skip_windows = pytest.mark.skipif(platform.system() == 'Windows', reason="Windows")

skip_glymur = pytest.mark.skipif(SKIP_GLYMUR, reason="Glymur can not be imported")

skip_ana = pytest.mark.skipif(SKIP_ANA, reason="ANA is not available")


Expand All @@ -52,19 +51,21 @@ def warnings_as_errors(request):

request.addfinalizer(lambda *args: warnings.resetwarnings())

new_hash_library = {}

figure_test_pngfiles = {}
hash_library = hash.hash_library
new_hash_library = {}
test_fig_dir = 'result_images_{:%H%M%S}'.format(datetime.datetime.now())


def figure_test(test_function):
"""
A decorator for a test that verifies the hash of the current figure or the returned figure,
with the name of the test function as the hash identifier in the library.
A PNG is also created with a temporary filename, with the lookup stored in the
`figure_test_pngfiles` dictionary.
A PNG is also created in the 'result_image' directory, which is created
on the current path.
All such decorated tests are marked with `pytest.mark.figure` for convenient filtering.
All such decorated tests are marked with `pytest.mark.figure` for
convenient filtering.
Examples
--------
Expand All @@ -77,16 +78,33 @@ def test_simple_plot():
def wrapper(*args, **kwargs):
if not os.path.exists(hash.HASH_LIBRARY_FILE):
pytest.xfail('Could not find a figure hash library at {}'.format(hash.HASH_LIBRARY_FILE))

name = "{0}.{1}".format(test_function.__module__,
test_function.__name__)
# Run the test function and get the figure
plt.figure()
name = "{0}.{1}".format(test_function.__module__, test_function.__name__)
pngfile = tempfile.NamedTemporaryFile(delete=False)
figure_hash = hash.hash_figure(test_function(*args, **kwargs), out_stream=pngfile)
figure_test_pngfiles[name] = pngfile.name
pngfile.close()
fig = test_function(*args, **kwargs)
if fig is None:
fig = plt.gcf()

# Save the image that was generated
if not os.path.exists(test_fig_dir):
os.mkdir(test_fig_dir)
result_image_loc = os.path.join(test_fig_dir, '{}.png'.format(name))
plt.savefig(result_image_loc)
plt.close()

# Create hash
imgdata = open(result_image_loc, "rb")
figure_hash = hash._hash_file(imgdata)
imgdata.close()

new_hash_library[name] = figure_hash
if name not in hash.hash_library:
if name not in hash_library:
pytest.fail("Hash not present: {0}".format(name))
else:
assert hash.hash_library[name] == figure_hash
plt.close()

if hash_library[name] != figure_hash:
raise RuntimeError('Figure hash does not match expected hash.\n'
'New image generated and placed at {}'.format(result_image_loc))

return wrapper

0 comments on commit 8aa1e10

Please sign in to comment.