Skip to content

Commit 3b0c9a7

Browse files
committed
Fix failing tests. The reasons for the failures were in the following categories:
- changes in the snapping algorithm that made the axes off by one pixel. - changes in text alignment. All the text in the baseline images is non-antialiased. This seems to be more robust to differences across freetype versions. This involved the addition of a new rcParam 'text.antialised', used only by the Agg backend. Additionally, some freetype-related differences still cause failures. For those, we mark the tests as known fail if the user has a version of freethe versions that we expect to worvesions were determined using T. Robitaille's freetype differences testing tool here: https://github.com/astrofrog/freetype_version_testing Fixes a bug in the SVG backend's Gouraud shading. Force the use of the Agg backend for testing, and restore the old backend afterward.
1 parent cb396f2 commit 3b0c9a7

File tree

531 files changed

+9427
-14432
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

531 files changed

+9427
-14432
lines changed

doc/devel/coding_guide.rst

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ it::
437437
from matplotlib.testing.decorators import image_comparison
438438
import matplotlib.pyplot as plt
439439

440-
@image_comparison(baseline_images=['spines_axes_positions.png'])
440+
@image_comparison(baseline_images=['spines_axes_positions'])
441441
def test_spines_axes_positions():
442442
# SF bug 2852168
443443
fig = plt.figure()
@@ -452,23 +452,25 @@ it::
452452
ax.xaxis.set_ticks_position('top')
453453
ax.spines['left'].set_color('none')
454454
ax.spines['bottom'].set_color('none')
455-
fig.savefig('spines_axes_positions.png')
456455

457-
The mechanism for comparing images is extremely simple -- it compares
458-
an image saved in the current directory with one from the Matplotlib
459-
sample_data repository. The correspondence is done by matching
460-
filenames, so ensure that:
456+
The first time this test is run, there will be no baseline image to
457+
compare against, so the test will fail. Copy the output images (in
458+
this case `result_images/test_category/spines_axes_positions.*`) to
459+
the `baseline_images` tree in the source directory (in this case
460+
`lib/matplotlib/tests/baseline_images/test_category`) and put them
461+
under source code revision control (with `git add`). When rerunning
462+
the tests, they should now pass.
461463

462-
* The filename given to :meth:`~matplotlib.figure.Figure.savefig` is
463-
exactly the same as the filename given to
464-
:func:`~matplotlib.testing.decorators.image_comparison` in the
465-
``baseline_images`` argument.
464+
There are two optional keyword arguments to the `image_comparison`
465+
decorator:
466466

467-
* The correct image gets added to the sample_data respository with
468-
the name ``test_baseline_<IMAGE_FILENAME.png>``. (See
469-
:ref:`sample-data` above for a description of how to add files to
470-
the sample_data repository.)
467+
- `extensions`: If you only wish to test some of the image formats
468+
(rather than the default `png`, `svg` and `pdf` formats), pass a
469+
list of the extensions to test.
471470

471+
- `tol`: This is the image matching tolerance, the default `1e-3`.
472+
If some variation is expected in the image between runs, this
473+
value may be adjusted.
472474

473475
Known failing tests
474476
-------------------

lib/matplotlib/__init__.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -992,22 +992,28 @@ def tk_window_focus():
992992

993993
def test(verbosity=0):
994994
"""run the matplotlib test suite"""
995-
import nose
996-
import nose.plugins.builtin
997-
from testing.noseclasses import KnownFailure
998-
from nose.plugins.manager import PluginManager
999-
1000-
# store the old values before overriding
1001-
plugins = []
1002-
plugins.append( KnownFailure() )
1003-
plugins.extend( [plugin() for plugin in nose.plugins.builtin.plugins] )
1004-
1005-
manager = PluginManager(plugins=plugins)
1006-
config = nose.config.Config(verbosity=verbosity, plugins=manager)
1007-
1008-
success = nose.run( defaultTest=default_test_modules,
1009-
config=config,
1010-
)
995+
old_backend = rcParams['backend']
996+
try:
997+
use('agg')
998+
import nose
999+
import nose.plugins.builtin
1000+
from testing.noseclasses import KnownFailure
1001+
from nose.plugins.manager import PluginManager
1002+
1003+
# store the old values before overriding
1004+
plugins = []
1005+
plugins.append( KnownFailure() )
1006+
plugins.extend( [plugin() for plugin in nose.plugins.builtin.plugins] )
1007+
1008+
manager = PluginManager(plugins=plugins)
1009+
config = nose.config.Config(verbosity=verbosity, plugins=manager)
1010+
1011+
success = nose.run( defaultTest=default_test_modules,
1012+
config=config,
1013+
)
1014+
finally:
1015+
if old_backend.lower() != 'agg':
1016+
use(old_backend)
10111017

10121018
return success
10131019

lib/matplotlib/backends/backend_agg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath):
150150
# We pass '0' for angle here, since it will be rotated (in raster
151151
# space) in the following call to draw_text_image).
152152
font.set_text(s, 0, flags=flags)
153-
font.draw_glyphs_to_bitmap()
153+
font.draw_glyphs_to_bitmap(antialiased=rcParams['text.antialiased'])
154154

155155
#print x, y, int(x), int(y), s
156156

lib/matplotlib/backends/backend_svg.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -691,13 +691,13 @@ def draw_gouraud_triangle(self, gc, points, colors, trans):
691691
href = '#GT%x' % self._n_gradients
692692
writer.element(
693693
'use',
694-
attrib={'xlink:href': '#%s' % href,
694+
attrib={'xlink:href': href,
695695
'fill': rgb2hex(avg_color),
696696
'fill-opacity': str(avg_color[-1])})
697697
for i in range(3):
698698
writer.element(
699699
'use',
700-
attrib={'xlink:href': '#%s' % href,
700+
attrib={'xlink:href': href,
701701
'fill': 'url(#GR%x_%d)' % (self._n_gradients, i),
702702
'fill-opacity': '1',
703703
'filter': 'url(#colorAdd)'})

lib/matplotlib/mathtext.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ def set_canvas_size(self, w, h, d):
209209

210210
def render_glyph(self, ox, oy, info):
211211
info.font.draw_glyph_to_bitmap(
212-
self.image, ox, oy - info.metrics.iceberg, info.glyph)
212+
self.image, ox, oy - info.metrics.iceberg, info.glyph,
213+
antialiased=rcParams['text.antialiased'])
213214

214215
def render_rect_filled(self, x1, y1, x2, y2):
215216
height = max(int(y2 - y1) - 1, 0)

lib/matplotlib/rcsetup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ def __call__(self, s):
406406
'text.latex.preview' : [False, validate_bool],
407407
'text.dvipnghack' : [None, validate_bool_maybe_none],
408408
'text.hinting' : [True, validate_bool],
409+
'text.antialiased' : [True, validate_bool],
409410

410411
# The following are deprecated and replaced by, e.g., 'font.style'
411412
#'text.fontstyle' : ['normal', str],

lib/matplotlib/testing/decorators.py

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import matplotlib.tests
77
import matplotlib.units
88
from matplotlib import pyplot as plt
9+
from matplotlib import ft2font
910
import numpy as np
1011
from matplotlib.testing.compare import comparable_formats, compare_images
1112
import warnings
@@ -63,7 +64,7 @@ def teardown_class(cls):
6364
matplotlib.units.registry.clear()
6465
matplotlib.units.registry.update(cls.original_units_registry)
6566
warnings.resetwarnings() #reset any warning filters set in tests
66-
67+
6768
def test(self):
6869
self._func()
6970

@@ -77,6 +78,18 @@ def cleanup(func):
7778
{'_func': func})
7879
return new_class
7980

81+
def check_freetype_version(ver):
82+
if ver is None:
83+
return True
84+
85+
from distutils import version
86+
if isinstance(ver, str):
87+
ver = (ver, ver)
88+
ver = [version.StrictVersion(x) for x in ver]
89+
found = version.StrictVersion(ft2font.__freetype_version__)
90+
91+
return found >= ver[0] and found <= ver[1]
92+
8093
class ImageComparisonTest(CleanupTest):
8194
@classmethod
8295
def setup_class(cls):
@@ -116,18 +129,25 @@ def do_test():
116129

117130
err = compare_images(expected_fname, actual_fname, self._tol, in_decorator=True)
118131

119-
if not os.path.exists(expected_fname):
120-
raise ImageComparisonFailure(
121-
'image does not exist: %s' % expected_fname)
122-
123-
if err:
124-
raise ImageComparisonFailure(
125-
'images not close: %(actual)s vs. %(expected)s '
126-
'(RMS %(rms).3f)'%err)
132+
try:
133+
if not os.path.exists(expected_fname):
134+
raise ImageComparisonFailure(
135+
'image does not exist: %s' % expected_fname)
136+
137+
if err:
138+
raise ImageComparisonFailure(
139+
'images not close: %(actual)s vs. %(expected)s '
140+
'(RMS %(rms).3f)'%err)
141+
except ImageComparisonFailure:
142+
if not check_freetype_version(self._freetype_version):
143+
raise KnownFailureTest(
144+
"Mismatched version of freetype. Test requires '%s', you have '%s'" %
145+
(self._freetype_version, ft2font.__freetype_version__))
146+
raise
127147

128148
yield (do_test,)
129149

130-
def image_comparison(baseline_images=None, extensions=None, tol=1e-3):
150+
def image_comparison(baseline_images=None, extensions=None, tol=1e-3, freetype_version=None):
131151
"""
132152
call signature::
133153
@@ -148,6 +168,13 @@ def image_comparison(baseline_images=None, extensions=None, tol=1e-3):
148168
If *None*, default to all supported extensions.
149169
150170
Otherwise, a list of extensions to test. For example ['png','pdf'].
171+
172+
*tol*: (default 1e-3)
173+
The RMS threshold above which the test is considered failed.
174+
175+
*freetype_version*: str or tuple
176+
The expected freetype version or range of versions for this
177+
test to pass.
151178
"""
152179

153180
if baseline_images is None:
@@ -178,7 +205,9 @@ def compare_images_decorator(func):
178205
{'_func': func,
179206
'_baseline_images': baseline_images,
180207
'_extensions': extensions,
181-
'_tol': tol})
208+
'_tol': tol,
209+
'_freetype_version': freetype_version})
210+
182211
return new_class
183212
return compare_images_decorator
184213

lib/matplotlib/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ def setup():
1111
rcdefaults() # Start with all defaults
1212
rcParams['font.family'] = 'Bitstream Vera Sans'
1313
rcParams['text.hinting'] = False
14+
rcParams['text.antialiased'] = False
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)