File: //opt/alt/python27/lib64/python2.7/site-packages/matplotlib/testing/decorators.py
from matplotlib.testing.noseclasses import KnownFailureTest, \
KnownFailureDidNotFailTest, ImageComparisonFailure
import os, sys, shutil
import nose
import matplotlib
import matplotlib.tests
import numpy as np
from matplotlib.testing.compare import comparable_formats, compare_images
def knownfailureif(fail_condition, msg=None, known_exception_class=None ):
"""
Assume a will fail if *fail_condition* is True. *fail_condition*
may also be False or the string 'indeterminate'.
*msg* is the error message displayed for the test.
If *known_exception_class* is not None, the failure is only known
if the exception is an instance of this class. (Default = None)
"""
# based on numpy.testing.dec.knownfailureif
if msg is None:
msg = 'Test known to fail'
def known_fail_decorator(f):
# Local import to avoid a hard nose dependency and only incur the
# import time overhead at actual test-time.
import nose
def failer(*args, **kwargs):
try:
# Always run the test (to generate images).
result = f(*args, **kwargs)
except Exception, err:
if fail_condition:
if known_exception_class is not None:
if not isinstance(err,known_exception_class):
# This is not the expected exception
raise
# (Keep the next ultra-long comment so in shows in console.)
raise KnownFailureTest(msg) # An error here when running nose means that you don't have the matplotlib.testing.noseclasses:KnownFailure plugin in use.
else:
raise
if fail_condition and fail_condition != 'indeterminate':
raise KnownFailureDidNotFailTest(msg)
return result
return nose.tools.make_decorator(f)(failer)
return known_fail_decorator
def image_comparison(baseline_images=None,extensions=None,tol=1e-3):
"""
call signature::
image_comparison(baseline_images=['my_figure'], extensions=None)
Compare images generated by the test with those specified in
*baseline_images*, which must correspond else an
ImageComparisonFailure exception will be raised.
Keyword arguments:
*baseline_images*: list
A list of strings specifying the names of the images generated
by calls to :meth:`matplotlib.figure.savefig`.
*extensions*: [ None | list ]
If *None*, default to all supported extensions.
Otherwise, a list of extensions to test. For example ['png','pdf'].
"""
if baseline_images is None:
raise ValueError('baseline_images must be specified')
if extensions is None:
# default extensions to test
extensions = ['png', 'pdf', 'svg']
# The multiple layers of defs are required because of how
# parameterized decorators work, and because we want to turn the
# single test_foo function to a generator that generates a
# separate test case for each file format.
def compare_images_decorator(func):
baseline_dir, result_dir = _image_directories(func)
def compare_images_generator():
for extension in extensions:
orig_expected_fnames = [os.path.join(baseline_dir,fname) + '.' + extension for fname in baseline_images]
expected_fnames = [os.path.join(result_dir,'expected-'+fname) + '.' + extension for fname in baseline_images]
for src,dst in zip( orig_expected_fnames, expected_fnames ):
shutil.copyfile(src,dst)
actual_fnames = [os.path.join(result_dir, fname) + '.' + extension for fname in baseline_images]
have_baseline_images = [os.path.exists(expected) for expected in expected_fnames]
have_baseline_image = np.all(have_baseline_images)
is_comparable = extension in comparable_formats()
if not is_comparable:
fail_msg = 'Cannot compare %s files on this system' % extension
elif not have_baseline_image:
fail_msg = 'Do not have baseline images %s' % expected_fnames
else:
fail_msg = 'No failure expected'
will_fail = not (is_comparable and have_baseline_image)
@knownfailureif(will_fail, fail_msg,
known_exception_class=ImageComparisonFailure )
def decorated_compare_images():
# set the default format of savefig
matplotlib.rc('savefig', extension=extension)
# change to the result directory for the duration of the test
old_dir = os.getcwd()
os.chdir(result_dir)
try:
result = func() # actually call the test function
finally:
os.chdir(old_dir)
for actual,expected in zip(actual_fnames,expected_fnames):
if not os.path.exists(expected):
raise ImageComparisonFailure(
'image does not exist: %s'%expected)
# compare the images
err = compare_images( expected, actual, tol,
in_decorator=True )
if err:
raise ImageComparisonFailure(
'images not close: %(actual)s vs. %(expected)s '
'(RMS %(rms).3f)'%err)
return result
yield (decorated_compare_images,)
return nose.tools.make_decorator(func)(compare_images_generator)
return compare_images_decorator
def _image_directories(func):
"""
Compute the baseline and result image directories for testing *func*.
Create the result directory if it doesn't exist.
"""
module_name = func.__module__
if module_name=='__main__':
# FIXME: this won't work for nested packages in matplotlib.tests
import warnings
warnings.warn('test module run as script. guessing baseline image locations')
script_name = sys.argv[0]
basedir = os.path.abspath(os.path.dirname(script_name))
subdir = os.path.splitext(os.path.split(script_name)[1])[0]
else:
mods = module_name.split('.')
assert mods.pop(0)=='matplotlib'
assert mods.pop(0)=='tests'
subdir = os.path.join(*mods)
basedir = os.path.dirname(matplotlib.tests.__file__)
baseline_dir = os.path.join(basedir,'baseline_images',subdir)
result_dir = os.path.abspath(os.path.join('result_images',subdir))
if not os.path.exists(result_dir):
os.makedirs(result_dir)
return baseline_dir, result_dir