diff --git a/doc/devel/testing.rst b/doc/devel/testing.rst index eae53c8602d4..0f78fa4d99b3 100644 --- a/doc/devel/testing.rst +++ b/doc/devel/testing.rst @@ -147,8 +147,8 @@ tests it:: from matplotlib.testing.decorators import image_comparison import matplotlib.pyplot as plt - @image_comparison(baseline_images=['line_dashes'], remove_text=True, - extensions=['png'], style='mpl20') + @image_comparison(baseline_images=['line_dashes.png'], remove_text=True, + style='mpl20') def test_line_dashes(): fig, ax = plt.subplots() ax.plot(range(10), linestyle=(0, (3, 3)), lw=5) @@ -161,6 +161,15 @@ case :file:`lib/matplotlib/tests/baseline_images/test_lines`). Put this new file under source code revision control (with ``git add``). When rerunning the tests, they should now pass. +If you wish to compare multiple file formats, then omit the extension from the +baseline image name and optionally pass the *extensions* argument:: + + @image_comparison(baseline_images=['line_dashes'], remove_text=True, + extensions=['png', 'svg'], style='mpl20') + def test_line_dashes(): + fig, ax = plt.subplots() + ax.plot(range(10), linestyle=(0, (3, 3)), lw=5) + It is preferred that new tests use ``style='mpl20'`` as this leads to smaller figures and reflects the newer look of default Matplotlib plots. Also, if the texts (labels, tick labels, etc) are not really part of what is tested, use the diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 46843841fe93..a58b6f88e5ea 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -919,8 +919,7 @@ def test_structured_data(): axs[1].plot("ones", "twos", "r", data=pts) -@image_comparison(['aitoff_proj'], extensions=["png"], - remove_text=True, style='mpl20') +@image_comparison(['aitoff_proj.png'], remove_text=True, style='mpl20') def test_aitoff_proj(): """ Test aitoff projection ref.: @@ -1410,7 +1409,7 @@ def test_pcolormesh(): ax3.pcolormesh(Qx, Qz, Zm, shading="gouraud") -@image_comparison(['pcolormesh_small'], extensions=["eps"]) +@image_comparison(['pcolormesh_small.eps']) def test_pcolormesh_small(): n = 3 x = np.linspace(-1.5, 1.5, n) @@ -2915,7 +2914,7 @@ def test_scatter_marker(self): edgecolors=['k', 'r', 'g', 'b'], marker=verts) - @image_comparison(['scatter_2D'], remove_text=True, extensions=['png']) + @image_comparison(['scatter_2D.png'], remove_text=True) def test_scatter_2D(self): x = np.arange(3) y = np.arange(2) @@ -5683,8 +5682,7 @@ def test_axline_args(): plt.draw() -@image_comparison(['vlines_basic', 'vlines_with_nan', 'vlines_masked'], - extensions=['png']) +@image_comparison(['vlines_basic.png', 'vlines_with_nan.png', 'vlines_masked.png']) def test_vlines(): # normal x1 = [2, 3, 4, 5, 7] @@ -5730,8 +5728,7 @@ def test_vlines_default(): assert mpl.colors.same_color(lines.get_color(), 'red') -@image_comparison(['hlines_basic', 'hlines_with_nan', 'hlines_masked'], - extensions=['png']) +@image_comparison(['hlines_basic.png', 'hlines_with_nan.png', 'hlines_masked.png']) def test_hlines(): # normal y1 = [2, 3, 4, 5, 7] @@ -5795,8 +5792,7 @@ def test_lines_with_colors(fig_test, fig_ref, data): colors=expect_color, linewidth=5) -@image_comparison(['vlines_hlines_blended_transform'], - extensions=['png'], style='mpl20') +@image_comparison(['vlines_hlines_blended_transform.png'], style='mpl20') def test_vlines_hlines_blended_transform(): t = np.arange(5.0, 10.0, 0.1) s = np.exp(-t) + np.sin(2 * np.pi * t) + 10 @@ -6492,8 +6488,8 @@ def test_pie_default(): autopct='%1.1f%%', shadow=True, startangle=90) -@image_comparison(['pie_linewidth_0', 'pie_linewidth_0', 'pie_linewidth_0'], - extensions=['png'], style='mpl20', tol=0.01) +@image_comparison(['pie_linewidth_0.png', 'pie_linewidth_0.png', 'pie_linewidth_0.png'], + style='mpl20', tol=0.01) def test_pie_linewidth_0(): # The slices will be ordered and plotted counter-clockwise. labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' diff --git a/lib/matplotlib/tests/test_bbox_tight.py b/lib/matplotlib/tests/test_bbox_tight.py index 9d430b78d5de..0bda0b6fbec3 100644 --- a/lib/matplotlib/tests/test_bbox_tight.py +++ b/lib/matplotlib/tests/test_bbox_tight.py @@ -167,8 +167,8 @@ def test_noop_tight_bbox(): assert im.shape == (7, 10, 4) -@image_comparison(['bbox_inches_fixed_aspect'], extensions=['png'], - remove_text=True, savefig_kwarg={'bbox_inches': 'tight'}) +@image_comparison(['bbox_inches_fixed_aspect.png'], remove_text=True, + savefig_kwarg={'bbox_inches': 'tight'}) def test_bbox_inches_fixed_aspect(): with plt.rc_context({'figure.constrained_layout.use': True}): fig, ax = plt.subplots() @@ -177,9 +177,8 @@ def test_bbox_inches_fixed_aspect(): ax.set_aspect('equal') -@image_comparison(['bbox_inches_inset_rasterized'], extensions=['pdf'], - remove_text=True, savefig_kwarg={'bbox_inches': 'tight'}, - style='mpl20') +@image_comparison(['bbox_inches_inset_rasterized.pdf'], remove_text=True, + savefig_kwarg={'bbox_inches': 'tight'}, style='mpl20') def test_bbox_inches_inset_rasterized(): fig, ax = plt.subplots() diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index c062e8c12b9c..c0ac4ac28c8b 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -491,7 +491,7 @@ def test_polycollection_close(): ax.set_ylim3d(0, 4) -@check_figures_equal(extensions=["png"]) +@check_figures_equal() def test_scalarmap_change_cmap(fig_test, fig_ref): # Ensure that changing the colormap of a 3D scatter after draw updates the colors. @@ -1314,8 +1314,7 @@ def test_set_offset_units(): np.testing.assert_allclose(off0, sc.get_offsets()) -@image_comparison(baseline_images=["test_check_masked_offsets"], - extensions=["png"], remove_text=True, style="mpl20") +@image_comparison(["test_check_masked_offsets.png"], remove_text=True, style="mpl20") def test_check_masked_offsets(): # Check if masked data is respected by scatter # Ref: Issue #24545 diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index 72e38d32e82f..f28ecb2d9bce 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -154,13 +154,12 @@ def test_colorbar_extension_inverted_axis(orientation, extend, expected): # TODO: tighten tolerance after baseline image is regenerated for text overhaul @pytest.mark.parametrize('use_gridspec', [True, False]) -@image_comparison(['cbar_with_orientation', - 'cbar_locationing', - 'double_cbar', - 'cbar_sharing', +@image_comparison(['cbar_with_orientation.png', + 'cbar_locationing.png', + 'double_cbar.png', + 'cbar_sharing.png', ], - extensions=['png'], remove_text=True, - savefig_kwarg={'dpi': 40}, tol=0.05) + remove_text=True, savefig_kwarg={'dpi': 40}, tol=0.05) def test_colorbar_positioning(use_gridspec): # Remove this line when this test image is regenerated. plt.rcParams['pcolormesh.snap'] = False diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 0aef16428f9f..24a2f31f7594 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -847,8 +847,7 @@ def test_cmap_and_norm_from_levels_and_colors(): ax.tick_params(labelleft=False, labelbottom=False) -@image_comparison(baseline_images=['boundarynorm_and_colorbar'], - extensions=['png'], tol=1.0) +@image_comparison(['boundarynorm_and_colorbar.png'], tol=1.0) def test_boundarynorm_and_colorbarbase(): # Remove this line when this test image is regenerated. plt.rcParams['pcolormesh.snap'] = False diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index f397aee2c9c4..e242c219df10 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -128,8 +128,8 @@ def test_contour_manual_moveto(): # TODO: tighten tolerance after baseline image is regenerated for text overhaul -@image_comparison(['contour_disconnected_segments'], - remove_text=True, style='mpl20', extensions=['png'], tol=0.01) +@image_comparison(['contour_disconnected_segments.png'], + remove_text=True, style='mpl20', tol=0.01) def test_contour_label_with_disconnected_segments(): x, y = np.mgrid[-1:1:21j, -1:1:21j] z = 1 / np.sqrt(0.01 + (x + 0.3) ** 2 + y ** 2) @@ -172,8 +172,7 @@ def test_given_colors_levels_and_extends(): plt.colorbar(c, ax=ax) -@image_comparison(['contourf_hatch_colors'], - remove_text=True, style='mpl20', extensions=['png']) +@image_comparison(['contourf_hatch_colors.png'], remove_text=True, style='mpl20') def test_hatch_colors(): fig, ax = plt.subplots() cf = ax.contourf([[0, 1], [1, 2]], hatches=['-', '/', '\\', '//'], cmap='gray') @@ -455,8 +454,7 @@ def test_contour_addlines(): assert_array_almost_equal(cb.ax.get_ylim(), [114.3091, 9972.30735], 3) -@image_comparison(baseline_images=['contour_uneven'], - extensions=['png'], remove_text=True, style='mpl20') +@image_comparison(['contour_uneven.png'], remove_text=True, style='mpl20') def test_contour_uneven(): # Remove this line when this test image is regenerated. plt.rcParams['pcolormesh.snap'] = False @@ -494,8 +492,7 @@ def test_label_nonagg(): plt.clabel(plt.contour([[1, 2], [3, 4]])) -@image_comparison(baseline_images=['contour_closed_line_loop'], - extensions=['png'], remove_text=True) +@image_comparison(['contour_closed_line_loop.png'], remove_text=True) def test_contour_closed_line_loop(): # github issue 19568. z = [[0, 0, 0], [0, 2, 0], [0, 0, 0], [2, 1, 2]] @@ -519,8 +516,7 @@ def test_quadcontourset_reuse(): assert qcs3._contour_generator == qcs1._contour_generator -@image_comparison(baseline_images=['contour_manual'], - extensions=['png'], remove_text=True, tol=0.89) +@image_comparison(['contour_manual.png'], remove_text=True, tol=0.89) def test_contour_manual(): # Manually specifying contour lines/polygons to plot. from matplotlib.contour import ContourSet @@ -545,8 +541,7 @@ def test_contour_manual(): ContourSet(ax, [2], [segs], [kinds], colors='k', linewidths=3) -@image_comparison(baseline_images=['contour_line_start_on_corner_edge'], - extensions=['png'], remove_text=True) +@image_comparison(['contour_line_start_on_corner_edge.png'], remove_text=True) def test_contour_line_start_on_corner_edge(): fig, ax = plt.subplots(figsize=(6, 5)) @@ -680,8 +675,7 @@ def test_algorithm_supports_corner_mask(algorithm): plt.contourf(z, algorithm=algorithm, corner_mask=True) -@image_comparison(baseline_images=['contour_all_algorithms'], - extensions=['png'], remove_text=True, tol=0.06) +@image_comparison(['contour_all_algorithms.png'], remove_text=True, tol=0.06) def test_all_algorithms(): algorithms = ['mpl2005', 'mpl2014', 'serial', 'threaded'] @@ -858,8 +852,8 @@ def test_allsegs_allkinds(): assert len(result[1]) == 4 -@image_comparison(baseline_images=['contour_rasterization'], - extensions=['pdf'], style='mpl20', savefig_kwarg={'dpi': 25}) +@image_comparison(['contour_rasterization.pdf'], savefig_kwarg={'dpi': 25}, + style='mpl20') def test_contourf_rasterize(): fig, ax = plt.subplots() data = [[0, 1], [1, 0]] @@ -868,7 +862,7 @@ def test_contourf_rasterize(): assert cs._rasterized -@check_figures_equal(extensions=["png"]) +@check_figures_equal() def test_contour_aliases(fig_test, fig_ref): data = np.arange(100).reshape((10, 10)) ** 2 fig_test.add_subplot().contour(data, linestyle=":") diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index ed608eebb6a7..b70701095bca 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -813,7 +813,7 @@ def test_boxstyle_errors(fmt, match): BoxStyle(fmt) -@image_comparison(baseline_images=['annulus'], extensions=['png']) +@image_comparison(['annulus.png']) def test_annulus(): fig, ax = plt.subplots() @@ -825,7 +825,7 @@ def test_annulus(): ax.set_aspect('equal') -@image_comparison(baseline_images=['annulus'], extensions=['png']) +@image_comparison(['annulus.png']) def test_annulus_setters(): fig, ax = plt.subplots() @@ -846,7 +846,7 @@ def test_annulus_setters(): ell.angle = 45 -@image_comparison(baseline_images=['annulus'], extensions=['png']) +@image_comparison(['annulus.png']) def test_annulus_setters2(): fig, ax = plt.subplots() diff --git a/lib/matplotlib/tests/test_text.py b/lib/matplotlib/tests/test_text.py index 551adbedbc61..0efb73a3a833 100644 --- a/lib/matplotlib/tests/test_text.py +++ b/lib/matplotlib/tests/test_text.py @@ -1136,8 +1136,7 @@ def test_empty_annotation_get_window_extent(): # TODO: tighten tolerance after baseline image is regenerated for text overhaul -@image_comparison(baseline_images=['basictext_wrap'], - extensions=['png'], tol=0.3) +@image_comparison(['basictext_wrap.png'], tol=0.3) def test_basic_wrap(): fig = plt.figure() plt.axis([0, 10, 0, 10]) @@ -1154,8 +1153,7 @@ def test_basic_wrap(): # TODO: tighten tolerance after baseline image is regenerated for text overhaul -@image_comparison(baseline_images=['fonttext_wrap'], - extensions=['png'], tol=0.3) +@image_comparison(['fonttext_wrap.png'], tol=0.3) def test_font_wrap(): fig = plt.figure() plt.axis([0, 10, 0, 10]) @@ -1188,8 +1186,8 @@ def test_va_for_angle(): # TODO: tighten tolerance after baseline image is regenerated for text overhaul -@image_comparison(baseline_images=['xtick_rotation_mode'], - remove_text=False, extensions=['png'], style='mpl20', tol=0.3) +@image_comparison(['xtick_rotation_mode.png'], remove_text=False, style='mpl20', + tol=0.3) def test_xtick_rotation_mode(): fig, ax = plt.subplots(figsize=(12, 1)) ax.set_yticks([]) @@ -1209,8 +1207,8 @@ def test_xtick_rotation_mode(): # TODO: tighten tolerance after baseline image is regenerated for text overhaul -@image_comparison(baseline_images=['ytick_rotation_mode'], - remove_text=False, extensions=['png'], style='mpl20', tol=0.3) +@image_comparison(['ytick_rotation_mode.png'], remove_text=False, style='mpl20', + tol=0.3) def test_ytick_rotation_mode(): fig, ax = plt.subplots(figsize=(1, 12)) ax.set_xticks([]) diff --git a/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py b/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py index f550dc9f531e..7f54466a3cce 100644 --- a/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py +++ b/lib/mpl_toolkits/axes_grid1/tests/test_axes_grid1.py @@ -62,7 +62,7 @@ def test_divider_append_axes(): # Update style when regenerating the test image -@image_comparison(['twin_axes_empty_and_removed'], extensions=["png"], tol=1, +@image_comparison(['twin_axes_empty_and_removed.png'], tol=1, style=('classic', '_classic_test_patch')) def test_twin_axes_empty_and_removed(): # Purely cosmetic font changes (avoid overlap) diff --git a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py index e9809ce2a106..7002a495c5d7 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -2200,9 +2200,7 @@ def test_subfigure_simple(): ax = sf[1].add_subplot(1, 1, 1, projection='3d', label='other') -# Update style when regenerating the test image -@image_comparison(baseline_images=['computed_zorder'], remove_text=True, - extensions=['png'], style=('mpl20')) +@image_comparison(['computed_zorder.png'], remove_text=True, style='mpl20') def test_computed_zorder(): plt.rcParams['axes3d.automargin'] = True # Remove when image is regenerated fig = plt.figure()