From c0462a5e1ce24af6a63f9bfee8978c36a316ac2d Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 5 Sep 2019 21:49:43 -0400 Subject: [PATCH 1/5] MNT/TST: generalize check_figures_equal to work with pytest.marks Generalize (at the cost of reaching a little bit into pytest internals) the check_figures_equal decorator so it works as expected with `pytest.mark.paramatarize` --- lib/matplotlib/testing/decorators.py | 68 ++++++++++++++++------------ lib/matplotlib/tests/test_testing.py | 16 ++++++- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/lib/matplotlib/testing/decorators.py b/lib/matplotlib/testing/decorators.py index 7965d45e4f16..5f7a0bd041a9 100644 --- a/lib/matplotlib/testing/decorators.py +++ b/lib/matplotlib/testing/decorators.py @@ -387,35 +387,45 @@ def decorator(func): _, result_dir = _image_directories(func) - if len(inspect.signature(func).parameters) == 2: - # Free-standing function. - @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 = result_dir / (func.__name__ + "." + ext) - ref_image_path = ( - 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) - - elif len(inspect.signature(func).parameters) == 3: - # Method. - @pytest.mark.parametrize("ext", extensions) - def wrapper(self, ext): - fig_test = plt.figure("test") - fig_ref = plt.figure("reference") - func(self, fig_test, fig_ref) - test_image_path = result_dir / (func.__name__ + "." + ext) - ref_image_path = ( - 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) + @pytest.mark.parametrize("ext", extensions) + def wrapper(*args, ext, **kwargs): + fig_test = plt.figure("test") + fig_ref = plt.figure("reference") + func(*args, fig_test=fig_test, fig_ref=fig_ref, **kwargs) + test_image_path = result_dir / (func.__name__ + "." + ext) + ref_image_path = 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 + ) + + sig = inspect.signature(func) + new_sig = sig.replace( + parameters=( + [ + param + for param in sig.parameters.values() + if param.name not in {"fig_test", "fig_ref"} + ] + + [ + inspect.Parameter( + "ext", inspect.Parameter.POSITIONAL_OR_KEYWORD + ) + ] + ) + ) + wrapper.__signature__ = new_sig + + # reach a bit into pytest internals to hoist the marks from + # our wrapped function + from _pytest.mark.structures import get_unpacked_marks + + wrapper.pytestmark = get_unpacked_marks( + wrapper + ) + get_unpacked_marks(func) return wrapper diff --git a/lib/matplotlib/tests/test_testing.py b/lib/matplotlib/tests/test_testing.py index 55415abb6a04..1d67d69a757d 100644 --- a/lib/matplotlib/tests/test_testing.py +++ b/lib/matplotlib/tests/test_testing.py @@ -1,7 +1,19 @@ import warnings import pytest +from matplotlib.testing.decorators import check_figures_equal -@pytest.mark.xfail(strict=True, - reason="testing that warnings fail tests") + +@pytest.mark.xfail( + strict=True, reason="testing that warnings fail tests" +) def test_warn_to_fail(): warnings.warn("This should fail the test") + + +@pytest.mark.parametrize("a", [1]) +@check_figures_equal(extensions=["png"]) +@pytest.mark.parametrize("b", [1]) +def test_paramatirize_with_check_figure_equal( + a, fig_ref, b, fig_test +): + assert a == b From f082265a0b8c94e2418d1b0f91e5adce6c96b796 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 7 Sep 2019 10:53:16 -0400 Subject: [PATCH 2/5] MNT: don't import from private pytest module --- lib/matplotlib/testing/decorators.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/testing/decorators.py b/lib/matplotlib/testing/decorators.py index 5f7a0bd041a9..20f867df1a3e 100644 --- a/lib/matplotlib/testing/decorators.py +++ b/lib/matplotlib/testing/decorators.py @@ -421,11 +421,8 @@ def wrapper(*args, ext, **kwargs): # reach a bit into pytest internals to hoist the marks from # our wrapped function - from _pytest.mark.structures import get_unpacked_marks - - wrapper.pytestmark = get_unpacked_marks( - wrapper - ) + get_unpacked_marks(func) + new_marks = getattr(func, 'pytestmark', []) + wrapper.pytestmark + wrapper.pytestmark = new_marks return wrapper From 922b57fb5723918a4b81b0930888ad0d1a925008 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 7 Sep 2019 11:09:52 -0400 Subject: [PATCH 3/5] MNT: fix spelling in test name --- lib/matplotlib/tests/test_testing.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/matplotlib/tests/test_testing.py b/lib/matplotlib/tests/test_testing.py index 1d67d69a757d..d1273ec1ba46 100644 --- a/lib/matplotlib/tests/test_testing.py +++ b/lib/matplotlib/tests/test_testing.py @@ -13,7 +13,5 @@ def test_warn_to_fail(): @pytest.mark.parametrize("a", [1]) @check_figures_equal(extensions=["png"]) @pytest.mark.parametrize("b", [1]) -def test_paramatirize_with_check_figure_equal( - a, fig_ref, b, fig_test -): +def test_parametrize_with_check_figure_equal(a, fig_ref, b, fig_test): assert a == b From cd4c42b1c2950d45eaae0a370d613cf8a0b396c8 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 3 Oct 2019 22:52:53 -0700 Subject: [PATCH 4/5] STY: condense code a bit --- lib/matplotlib/testing/decorators.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/testing/decorators.py b/lib/matplotlib/testing/decorators.py index 20f867df1a3e..0536af9a3e4a 100644 --- a/lib/matplotlib/testing/decorators.py +++ b/lib/matplotlib/testing/decorators.py @@ -381,6 +381,7 @@ def test_plot(fig_test, fig_ref): fig_test.subplots().plot([1, 3, 5]) fig_ref.subplots().plot([0, 1, 2], [1, 3, 5]) """ + POK = inspect.Parameter.POSITIONAL_OR_KEYWORD def decorator(func): import pytest @@ -410,18 +411,14 @@ def wrapper(*args, ext, **kwargs): for param in sig.parameters.values() if param.name not in {"fig_test", "fig_ref"} ] - + [ - inspect.Parameter( - "ext", inspect.Parameter.POSITIONAL_OR_KEYWORD - ) - ] + + [inspect.Parameter("ext", POK)] ) ) wrapper.__signature__ = new_sig # reach a bit into pytest internals to hoist the marks from # our wrapped function - new_marks = getattr(func, 'pytestmark', []) + wrapper.pytestmark + new_marks = getattr(func, "pytestmark", []) + wrapper.pytestmark wrapper.pytestmark = new_marks return wrapper From e10850e89dec5d05ec3e5f20e54cd9b2ee8bce24 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 3 Oct 2019 23:02:03 -0700 Subject: [PATCH 5/5] STY: condense code some more --- lib/matplotlib/testing/decorators.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/testing/decorators.py b/lib/matplotlib/testing/decorators.py index 0536af9a3e4a..7e9621cb3b1d 100644 --- a/lib/matplotlib/testing/decorators.py +++ b/lib/matplotlib/testing/decorators.py @@ -381,8 +381,7 @@ def test_plot(fig_test, fig_ref): fig_test.subplots().plot([1, 3, 5]) fig_ref.subplots().plot([0, 1, 2], [1, 3, 5]) """ - POK = inspect.Parameter.POSITIONAL_OR_KEYWORD - + POSITIONAL_OR_KEYWORD = inspect.Parameter.POSITIONAL_OR_KEYWORD def decorator(func): import pytest @@ -405,14 +404,10 @@ def wrapper(*args, ext, **kwargs): sig = inspect.signature(func) new_sig = sig.replace( - parameters=( - [ - param - for param in sig.parameters.values() - if param.name not in {"fig_test", "fig_ref"} - ] - + [inspect.Parameter("ext", POK)] - ) + parameters=([param + for param in sig.parameters.values() + if param.name not in {"fig_test", "fig_ref"}] + + [inspect.Parameter("ext", POSITIONAL_OR_KEYWORD)]) ) wrapper.__signature__ = new_sig