diff --git a/lib/matplotlib/testing/decorators.py b/lib/matplotlib/testing/decorators.py index 97fcf23a4cb7..85b8d5e87d6b 100644 --- a/lib/matplotlib/testing/decorators.py +++ b/lib/matplotlib/testing/decorators.py @@ -407,6 +407,46 @@ def image_comparison(baseline_images, extensions=None, tol=0, savefig_kwargs=savefig_kwarg, style=style) +def check_figures_equal(*, extensions=("png", "pdf", "svg"), tol=0): + """ + Decorator for test cases that generate and compare two figures. + + The decorated function must take two arguments, *fig_test* and *fig_ref*, + and draw the test and reference images on them. After the function + returns, the figures are saved and compared. + + Arguments + --------- + extensions : list, default: ["png", "pdf", "svg"] + The extensions to test. + tol : float + The RMS threshold above which the test is considered failed. + """ + + def decorator(func): + import pytest + + _, result_dir = map(Path, _image_directories(func)) + + @pytest.mark.parametrize("ext", extensions) + def wrapper(ext): + fig_test = plt.figure("test") + fig_ref = plt.figure("reference") + func(fig_test, fig_ref) + test_image_path = str( + result_dir / (func.__name__ + "." + ext)) + ref_image_path = str( + result_dir / (func.__name__ + "-expected." + ext)) + fig_test.savefig(test_image_path) + fig_ref.savefig(ref_image_path) + _raise_on_image_difference( + ref_image_path, test_image_path, tol=tol) + + return wrapper + + return decorator + + def _image_directories(func): """ Compute the baseline and result image directories for testing *func*. diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 83a3973f032c..fda0fe0f362b 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -14,7 +14,7 @@ import warnings import matplotlib -from matplotlib.testing.decorators import image_comparison +from matplotlib.testing.decorators import image_comparison, check_figures_equal import matplotlib.pyplot as plt import matplotlib.markers as mmarkers import matplotlib.patches as mpatches @@ -5702,18 +5702,11 @@ def test_plot_columns_cycle_deprecation(): plt.plot(np.zeros((2, 2)), np.zeros((2, 3))) -def test_markerfacecolor_none_alpha(): - fig1, ax1 = plt.subplots() - ax1.plot(0, "o", mfc="none", alpha=.5) - buf1 = io.BytesIO() - fig1.savefig(buf1) - - fig2, ax2 = plt.subplots() - ax2.plot(0, "o", mfc="w", alpha=.5) - buf2 = io.BytesIO() - fig2.savefig(buf2) - - assert buf1.getvalue() == buf2.getvalue() +# pdf and svg tests fail using travis' old versions of gs and inkscape. +@check_figures_equal(extensions=["png"]) +def test_markerfacecolor_none_alpha(fig_test, fig_ref): + fig_test.subplots().plot(0, "o", mfc="none", alpha=.5) + fig_ref.subplots().plot(0, "o", mfc="w", alpha=.5) def test_tick_padding_tightbbox(): diff --git a/tools/triage_tests.py b/tools/triage_tests.py index c8c60f8142b2..cac1bc38b660 100644 --- a/tools/triage_tests.py +++ b/tools/triage_tests.py @@ -192,14 +192,22 @@ def set_large_image(self, index): self.thumbnails[self.current_thumbnail].setFrameShape(1) def accept_test(self): - self.entries[self.current_entry].accept() + entry = self.entries[self.current_entry] + if entry.status == 'autogen': + print('Cannot accept autogenerated test cases.') + return + entry.accept() self.filelist.currentItem().setText( self.entries[self.current_entry].display) # Auto-move to the next entry self.set_entry(min((self.current_entry + 1), len(self.entries) - 1)) def reject_test(self): - self.entries[self.current_entry].reject() + entry = self.entries[self.current_entry] + if entry.status == 'autogen': + print('Cannot reject autogenerated test cases.') + return + entry.reject() self.filelist.currentItem().setText( self.entries[self.current_entry].display) # Auto-move to the next entry @@ -261,11 +269,14 @@ def __init__(self, path, root, source): ] self.thumbnails = [os.path.join(self.dir, x) for x in self.thumbnails] - self.status = 'unknown' - - if self.same(os.path.join(self.dir, self.generated), + if not Path(self.destdir, self.generated).exists(): + # This case arises from a check_figures_equal test. + self.status = 'autogen' + elif self.same(os.path.join(self.dir, self.generated), os.path.join(self.destdir, self.generated)): self.status = 'accept' + else: + self.status = 'unknown' def same(self, a, b): """ @@ -297,16 +308,18 @@ def display(self): Get the display string for this entry. This is the text that appears in the list widget. """ - status_map = {'unknown': '\N{BALLOT BOX}', - 'accept': '\N{BALLOT BOX WITH CHECK}', - 'reject': '\N{BALLOT BOX WITH X}'} + status_map = { + 'unknown': '\N{BALLOT BOX}', + 'accept': '\N{BALLOT BOX WITH CHECK}', + 'reject': '\N{BALLOT BOX WITH X}', + 'autogen': '\N{WHITE SQUARE CONTAINING BLACK SMALL SQUARE}', + } box = status_map[self.status] return '{} {} [{}]'.format(box, self.name, self.extension) def accept(self): """ - Accept this test by copying the generated result to the - source tree. + Accept this test by copying the generated result to the source tree. """ a = os.path.join(self.dir, self.generated) b = os.path.join(self.destdir, self.generated) @@ -315,8 +328,7 @@ def accept(self): def reject(self): """ - Reject this test by copying the expected result to the - source tree. + Reject this test by copying the expected result to the source tree. """ a = os.path.join(self.dir, self.expected) b = os.path.join(self.destdir, self.generated) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy