From 34bc2fca9a6ad5248a609f64dcdba436948c9ba8 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 10 Jun 2022 16:28:00 +0100 Subject: [PATCH 01/23] pytest parametrize gallery tests --- docs/gallery_code/general/plot_inset.py | 2 +- .../meteorology/plot_hovmoller.py | 3 ++ docs/gallery_tests/gallerytest_util.py | 20 +++++++++++-- ...plot_inset.py => test_gallery_examples.py} | 25 +++++++++------- docs/gallery_tests/test_plot_COP_1d.py | 30 ------------------- docs/gallery_tests/test_plot_COP_maps.py | 30 ------------------- docs/gallery_tests/test_plot_SOI_filtering.py | 30 ------------------- docs/gallery_tests/test_plot_TEC.py | 30 ------------------- .../test_plot_anomaly_log_colouring.py | 30 ------------------- .../test_plot_atlantic_profiles.py | 30 ------------------- docs/gallery_tests/test_plot_coriolis.py | 27 ----------------- docs/gallery_tests/test_plot_cross_section.py | 30 ------------------- .../test_plot_custom_aggregation.py | 30 ------------------- .../test_plot_custom_file_loading.py | 30 ------------------- .../test_plot_deriving_phenomena.py | 30 ------------------- docs/gallery_tests/test_plot_global_map.py | 30 ------------------- docs/gallery_tests/test_plot_hovmoller.py | 30 ------------------- .../test_plot_lagged_ensemble.py | 30 ------------------- .../test_plot_lineplot_with_legend.py | 30 ------------------- docs/gallery_tests/test_plot_load_nemo.py | 30 ------------------- .../test_plot_orca_projection.py | 30 ------------------- docs/gallery_tests/test_plot_polar_stereo.py | 30 ------------------- .../gallery_tests/test_plot_polynomial_fit.py | 30 ------------------- .../test_plot_projections_and_annotations.py | 30 ------------------- .../test_plot_rotated_pole_mapping.py | 30 ------------------- docs/gallery_tests/test_plot_wind_barbs.py | 30 ------------------- docs/gallery_tests/test_plot_wind_speed.py | 30 ------------------- 27 files changed, 36 insertions(+), 701 deletions(-) rename docs/gallery_tests/{test_plot_inset.py => test_gallery_examples.py} (52%) delete mode 100644 docs/gallery_tests/test_plot_COP_1d.py delete mode 100644 docs/gallery_tests/test_plot_COP_maps.py delete mode 100644 docs/gallery_tests/test_plot_SOI_filtering.py delete mode 100644 docs/gallery_tests/test_plot_TEC.py delete mode 100644 docs/gallery_tests/test_plot_anomaly_log_colouring.py delete mode 100644 docs/gallery_tests/test_plot_atlantic_profiles.py delete mode 100644 docs/gallery_tests/test_plot_coriolis.py delete mode 100644 docs/gallery_tests/test_plot_cross_section.py delete mode 100644 docs/gallery_tests/test_plot_custom_aggregation.py delete mode 100644 docs/gallery_tests/test_plot_custom_file_loading.py delete mode 100644 docs/gallery_tests/test_plot_deriving_phenomena.py delete mode 100644 docs/gallery_tests/test_plot_global_map.py delete mode 100644 docs/gallery_tests/test_plot_hovmoller.py delete mode 100644 docs/gallery_tests/test_plot_lagged_ensemble.py delete mode 100644 docs/gallery_tests/test_plot_lineplot_with_legend.py delete mode 100644 docs/gallery_tests/test_plot_load_nemo.py delete mode 100644 docs/gallery_tests/test_plot_orca_projection.py delete mode 100644 docs/gallery_tests/test_plot_polar_stereo.py delete mode 100644 docs/gallery_tests/test_plot_polynomial_fit.py delete mode 100644 docs/gallery_tests/test_plot_projections_and_annotations.py delete mode 100644 docs/gallery_tests/test_plot_rotated_pole_mapping.py delete mode 100644 docs/gallery_tests/test_plot_wind_barbs.py delete mode 100644 docs/gallery_tests/test_plot_wind_speed.py diff --git a/docs/gallery_code/general/plot_inset.py b/docs/gallery_code/general/plot_inset.py index 004d01bc6f..c0d3827d55 100644 --- a/docs/gallery_code/general/plot_inset.py +++ b/docs/gallery_code/general/plot_inset.py @@ -56,7 +56,7 @@ def main(): # Manually set the orientation and tick marks on your colour bar ticklist = np.linspace(np.min(region.data), np.max(region.data), 4) plt.colorbar(orientation="horizontal", ticks=ticklist) - ax_sub.set_title("Data Region") + ax_sub.set_title("Data Region", color="r") # Add coastlines ax_sub.coastlines() # request to show entire map, using the colour mesh on the data region only diff --git a/docs/gallery_code/meteorology/plot_hovmoller.py b/docs/gallery_code/meteorology/plot_hovmoller.py index e9f8207a94..2269086dd5 100644 --- a/docs/gallery_code/meteorology/plot_hovmoller.py +++ b/docs/gallery_code/meteorology/plot_hovmoller.py @@ -15,9 +15,12 @@ import iris import iris.plot as iplt import iris.quickplot as qplt +import iris.util def main(): + iris.util.approx_equal(3, 4) + # load a single cube of surface temperature between +/- 5 latitude fname = iris.sample_data_path("ostia_monthly.nc") cube = iris.load_cube( diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index eb2736f194..2db43be6a1 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -10,8 +10,10 @@ """ +import collections import contextlib import os.path +import pathlib import sys import warnings @@ -21,6 +23,7 @@ from iris._deprecation import IrisDeprecation import iris.plot as iplt import iris.quickplot as qplt +from iris.tests import check_graphic GALLERY_DIRECTORY = os.path.join( os.path.dirname(os.path.dirname(__file__)), "gallery_code" @@ -47,17 +50,20 @@ def add_gallery_to_path(): @contextlib.contextmanager -def show_replaced_by_check_graphic(test_case): +def show_replaced_by_check_graphic(test_id): """ Creates a context manager which can be used to replace the functionality of matplotlib.pyplot.show with a function which calls the check_graphic - method on the given test_case (iris.tests.IrisTest.check_graphic). + function (iris.tests.check_graphic). """ + assertion_counts = collections.defaultdict(int) def replacement_show(): # form a closure on test_case and tolerance - test_case.check_graphic() + unique_id = f"{test_id}.{assertion_counts[test_id]}" + assertion_counts[test_id] += 1 + check_graphic(unique_id) orig_show = plt.show plt.show = iplt.show = qplt.show = replacement_show @@ -84,3 +90,11 @@ def fail_any_deprecation_warnings(): del default_future_kwargs[dead_option] with iris.FUTURE.context(**default_future_kwargs): yield + + +def gallery_examples(): + """Generator to yield all current gallery examples.""" + current_dir = pathlib.Path(__file__).resolve() + code_dir = current_dir.parents[1] / "gallery_code" + for example_file in code_dir.glob("*/plot*.py"): + yield example_file.stem diff --git a/docs/gallery_tests/test_plot_inset.py b/docs/gallery_tests/test_gallery_examples.py similarity index 52% rename from docs/gallery_tests/test_plot_inset.py rename to docs/gallery_tests/test_gallery_examples.py index 739e0a3224..ab0cb183b0 100644 --- a/docs/gallery_tests/test_plot_inset.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -4,27 +4,32 @@ # See COPYING and COPYING.LESSER in the root of the repository for full # licensing details. +import importlib + +import pytest + # Import Iris tests first so that some things can be initialised before # importing anything else. - import iris.tests as tests from .gallerytest_util import ( add_gallery_to_path, fail_any_deprecation_warnings, + gallery_examples, show_replaced_by_check_graphic, ) -class TestInsetPlot(tests.GraphicsTest): - """Test the inset plot gallery code.""" - - def test_plot_inset(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_inset - with show_replaced_by_check_graphic(self): - plot_inset.main() +@pytest.mark.parametrize("example_code", gallery_examples()) +def test_plot_example(example_code): + with fail_any_deprecation_warnings(): + with add_gallery_to_path(): + module = importlib.import_module(example_code) + print(module.__file__) + with show_replaced_by_check_graphic( + f"gallery_tests.test_{example_code}" + ): + module.main() if __name__ == "__main__": diff --git a/docs/gallery_tests/test_plot_COP_1d.py b/docs/gallery_tests/test_plot_COP_1d.py deleted file mode 100644 index 9771e10fb1..0000000000 --- a/docs/gallery_tests/test_plot_COP_1d.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestCOP1DPlot(tests.GraphicsTest): - """Test the COP_1d_plot gallery code.""" - - def test_plot_COP_1d(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_COP_1d - with show_replaced_by_check_graphic(self): - plot_COP_1d.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_COP_maps.py b/docs/gallery_tests/test_plot_COP_maps.py deleted file mode 100644 index a01e12527f..0000000000 --- a/docs/gallery_tests/test_plot_COP_maps.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestCOPMaps(tests.GraphicsTest): - """Test the COP_maps gallery code.""" - - def test_plot_cop_maps(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_COP_maps - with show_replaced_by_check_graphic(self): - plot_COP_maps.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_SOI_filtering.py b/docs/gallery_tests/test_plot_SOI_filtering.py deleted file mode 100644 index 1da731122a..0000000000 --- a/docs/gallery_tests/test_plot_SOI_filtering.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestSOIFiltering(tests.GraphicsTest): - """Test the SOI_filtering gallery code.""" - - def test_plot_soi_filtering(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_SOI_filtering - with show_replaced_by_check_graphic(self): - plot_SOI_filtering.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_TEC.py b/docs/gallery_tests/test_plot_TEC.py deleted file mode 100644 index cfc1fb8eec..0000000000 --- a/docs/gallery_tests/test_plot_TEC.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestTEC(tests.GraphicsTest): - """Test the TEC gallery code.""" - - def test_plot_TEC(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_TEC - with show_replaced_by_check_graphic(self): - plot_TEC.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_anomaly_log_colouring.py b/docs/gallery_tests/test_plot_anomaly_log_colouring.py deleted file mode 100644 index 41f76cc774..0000000000 --- a/docs/gallery_tests/test_plot_anomaly_log_colouring.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestAnomalyLogColouring(tests.GraphicsTest): - """Test the anomaly colouring gallery code.""" - - def test_plot_anomaly_log_colouring(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_anomaly_log_colouring - with show_replaced_by_check_graphic(self): - plot_anomaly_log_colouring.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_atlantic_profiles.py b/docs/gallery_tests/test_plot_atlantic_profiles.py deleted file mode 100644 index fdcb5fb1d1..0000000000 --- a/docs/gallery_tests/test_plot_atlantic_profiles.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestAtlanticProfiles(tests.GraphicsTest): - """Test the atlantic_profiles gallery code.""" - - def test_plot_atlantic_profiles(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_atlantic_profiles - with show_replaced_by_check_graphic(self): - plot_atlantic_profiles.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_coriolis.py b/docs/gallery_tests/test_plot_coriolis.py deleted file mode 100644 index 2e4cea8a74..0000000000 --- a/docs/gallery_tests/test_plot_coriolis.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. - -import iris.tests as tests - -from . import gallerytest_util - -with gallerytest_util.add_gallery_to_path(): - import plot_coriolis - - -class TestCoriolisPlot(tests.GraphicsTest): - """Test the Coriolis Plot gallery code.""" - - def test_plot_coriolis(self): - with gallerytest_util.show_replaced_by_check_graphic(self): - plot_coriolis.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_cross_section.py b/docs/gallery_tests/test_plot_cross_section.py deleted file mode 100644 index b0878d10bc..0000000000 --- a/docs/gallery_tests/test_plot_cross_section.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestCrossSection(tests.GraphicsTest): - """Test the cross_section gallery code.""" - - def test_plot_cross_section(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_cross_section - with show_replaced_by_check_graphic(self): - plot_cross_section.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_custom_aggregation.py b/docs/gallery_tests/test_plot_custom_aggregation.py deleted file mode 100644 index 9d0a40dd3c..0000000000 --- a/docs/gallery_tests/test_plot_custom_aggregation.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestCustomAggregation(tests.GraphicsTest): - """Test the custom aggregation gallery code.""" - - def test_plot_custom_aggregation(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_custom_aggregation - with show_replaced_by_check_graphic(self): - plot_custom_aggregation.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_custom_file_loading.py b/docs/gallery_tests/test_plot_custom_file_loading.py deleted file mode 100644 index 4d0d603a22..0000000000 --- a/docs/gallery_tests/test_plot_custom_file_loading.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestCustomFileLoading(tests.GraphicsTest): - """Test the custom_file_loading gallery code.""" - - def test_plot_custom_file_loading(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_custom_file_loading - with show_replaced_by_check_graphic(self): - plot_custom_file_loading.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_deriving_phenomena.py b/docs/gallery_tests/test_plot_deriving_phenomena.py deleted file mode 100644 index ef2f8cec87..0000000000 --- a/docs/gallery_tests/test_plot_deriving_phenomena.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestDerivingPhenomena(tests.GraphicsTest): - """Test the deriving_phenomena gallery code.""" - - def test_plot_deriving_phenomena(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_deriving_phenomena - with show_replaced_by_check_graphic(self): - plot_deriving_phenomena.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_global_map.py b/docs/gallery_tests/test_plot_global_map.py deleted file mode 100644 index 16f769deae..0000000000 --- a/docs/gallery_tests/test_plot_global_map.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestGlobalMap(tests.GraphicsTest): - """Test the global_map gallery code.""" - - def test_plot_global_map(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_global_map - with show_replaced_by_check_graphic(self): - plot_global_map.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_hovmoller.py b/docs/gallery_tests/test_plot_hovmoller.py deleted file mode 100644 index 29c0e72e05..0000000000 --- a/docs/gallery_tests/test_plot_hovmoller.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestGlobalMap(tests.GraphicsTest): - """Test the hovmoller gallery code.""" - - def test_plot_hovmoller(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_hovmoller - with show_replaced_by_check_graphic(self): - plot_hovmoller.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_lagged_ensemble.py b/docs/gallery_tests/test_plot_lagged_ensemble.py deleted file mode 100644 index f0a0201613..0000000000 --- a/docs/gallery_tests/test_plot_lagged_ensemble.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestLaggedEnsemble(tests.GraphicsTest): - """Test the lagged ensemble gallery code.""" - - def test_plot_lagged_ensemble(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_lagged_ensemble - with show_replaced_by_check_graphic(self): - plot_lagged_ensemble.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_lineplot_with_legend.py b/docs/gallery_tests/test_plot_lineplot_with_legend.py deleted file mode 100644 index 5677667026..0000000000 --- a/docs/gallery_tests/test_plot_lineplot_with_legend.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestLineplotWithLegend(tests.GraphicsTest): - """Test the lineplot_with_legend gallery code.""" - - def test_plot_lineplot_with_legend(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_lineplot_with_legend - with show_replaced_by_check_graphic(self): - plot_lineplot_with_legend.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_load_nemo.py b/docs/gallery_tests/test_plot_load_nemo.py deleted file mode 100644 index f250dc46b4..0000000000 --- a/docs/gallery_tests/test_plot_load_nemo.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestLoadNemo(tests.GraphicsTest): - """Test the load_nemo gallery code.""" - - def test_plot_load_nemo(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_load_nemo - with show_replaced_by_check_graphic(self): - plot_load_nemo.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_orca_projection.py b/docs/gallery_tests/test_plot_orca_projection.py deleted file mode 100644 index c4058c996e..0000000000 --- a/docs/gallery_tests/test_plot_orca_projection.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestOrcaProjection(tests.GraphicsTest): - """Test the orca projection gallery code.""" - - def test_plot_orca_projection(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_orca_projection - with show_replaced_by_check_graphic(self): - plot_orca_projection.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_polar_stereo.py b/docs/gallery_tests/test_plot_polar_stereo.py deleted file mode 100644 index 4d32ee5830..0000000000 --- a/docs/gallery_tests/test_plot_polar_stereo.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestPolarStereo(tests.GraphicsTest): - """Test the polar_stereo gallery code.""" - - def test_plot_polar_stereo(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_polar_stereo - with show_replaced_by_check_graphic(self): - plot_polar_stereo.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_polynomial_fit.py b/docs/gallery_tests/test_plot_polynomial_fit.py deleted file mode 100644 index b522dcf43c..0000000000 --- a/docs/gallery_tests/test_plot_polynomial_fit.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestPolynomialFit(tests.GraphicsTest): - """Test the polynomial_fit gallery code.""" - - def test_plot_polynomial_fit(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_polynomial_fit - with show_replaced_by_check_graphic(self): - plot_polynomial_fit.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_projections_and_annotations.py b/docs/gallery_tests/test_plot_projections_and_annotations.py deleted file mode 100644 index 1c24202251..0000000000 --- a/docs/gallery_tests/test_plot_projections_and_annotations.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestProjectionsAndAnnotations(tests.GraphicsTest): - """Test the atlantic_profiles gallery code.""" - - def test_plot_projections_and_annotations(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_projections_and_annotations - with show_replaced_by_check_graphic(self): - plot_projections_and_annotations.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_rotated_pole_mapping.py b/docs/gallery_tests/test_plot_rotated_pole_mapping.py deleted file mode 100644 index cd9b04fc66..0000000000 --- a/docs/gallery_tests/test_plot_rotated_pole_mapping.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestRotatedPoleMapping(tests.GraphicsTest): - """Test the rotated_pole_mapping gallery code.""" - - def test_plot_rotated_pole_mapping(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_rotated_pole_mapping - with show_replaced_by_check_graphic(self): - plot_rotated_pole_mapping.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_wind_barbs.py b/docs/gallery_tests/test_plot_wind_barbs.py deleted file mode 100644 index 6003860a5e..0000000000 --- a/docs/gallery_tests/test_plot_wind_barbs.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestWindBarbs(tests.GraphicsTest): - """Test the wind_barbs example code.""" - - def test_wind_barbs(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_wind_barbs - with show_replaced_by_check_graphic(self): - plot_wind_barbs.main() - - -if __name__ == "__main__": - tests.main() diff --git a/docs/gallery_tests/test_plot_wind_speed.py b/docs/gallery_tests/test_plot_wind_speed.py deleted file mode 100644 index ebaf97adbe..0000000000 --- a/docs/gallery_tests/test_plot_wind_speed.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - show_replaced_by_check_graphic, -) - - -class TestWindSpeed(tests.GraphicsTest): - """Test the wind_speed gallery code.""" - - def test_plot_wind_speed(self): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - import plot_wind_speed - with show_replaced_by_check_graphic(self): - plot_wind_speed.main() - - -if __name__ == "__main__": - tests.main() From f5f71f496fa0261bb342276a71c9f7a0e29bb5a7 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 14 Jun 2022 16:31:54 +0100 Subject: [PATCH 02/23] two context managers as fixtures --- docs/gallery_tests/conftest.py | 64 +++++++++++++++++++++ docs/gallery_tests/gallerytest_util.py | 49 ---------------- docs/gallery_tests/test_gallery_examples.py | 30 +++------- 3 files changed, 71 insertions(+), 72 deletions(-) create mode 100644 docs/gallery_tests/conftest.py diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py new file mode 100644 index 0000000000..eacd0f9b55 --- /dev/null +++ b/docs/gallery_tests/conftest.py @@ -0,0 +1,64 @@ +# Copyright Iris contributors +# +# This file is part of Iris and is released under the LGPL license. +# See COPYING and COPYING.LESSER in the root of the repository for full +# licensing details. + +""" +Provides context managers which are fundamental to the ability +to run the gallery tests. + +""" + +import os.path +import sys +import warnings + +import pytest + +import iris +from iris._deprecation import IrisDeprecation + +GALLERY_DIRECTORY = os.path.join( + os.path.dirname(os.path.dirname(__file__)), "gallery_code" +) +GALLERY_DIRECTORIES = [ + os.path.join(GALLERY_DIRECTORY, the_dir) + for the_dir in os.listdir(GALLERY_DIRECTORY) +] + + +@pytest.fixture +def add_gallery_to_path(): + """ + Creates a fixture which can be used to add the iris gallery to the + PYTHONPATH. The gallery entries are only importable throughout the lifetime + of this context manager. + + """ + orig_sys_path = sys.path + sys.path = sys.path[:] + sys.path += GALLERY_DIRECTORIES + yield + sys.path = orig_sys_path + + +@pytest.fixture +def fail_any_deprecation_warnings(): + """ + Create a fixture in which any deprecation warning will cause an error. + + The context also resets all the iris.FUTURE settings to the defaults, as + otherwise changes made in one test can affect subsequent ones. + + """ + with warnings.catch_warnings(): + # Detect and error all and any Iris deprecation warnings. + warnings.simplefilter("error", IrisDeprecation) + # Run with all default settings in iris.FUTURE. + default_future_kwargs = iris.Future().__dict__.copy() + for dead_option in iris.Future.deprecated_options: + # Avoid a warning when setting these ! + del default_future_kwargs[dead_option] + with iris.FUTURE.context(**default_future_kwargs): + yield diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index 2db43be6a1..5d101e82fb 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -12,42 +12,14 @@ import collections import contextlib -import os.path import pathlib -import sys -import warnings import matplotlib.pyplot as plt -import iris -from iris._deprecation import IrisDeprecation import iris.plot as iplt import iris.quickplot as qplt from iris.tests import check_graphic -GALLERY_DIRECTORY = os.path.join( - os.path.dirname(os.path.dirname(__file__)), "gallery_code" -) -GALLERY_DIRECTORIES = [ - os.path.join(GALLERY_DIRECTORY, the_dir) - for the_dir in os.listdir(GALLERY_DIRECTORY) -] - - -@contextlib.contextmanager -def add_gallery_to_path(): - """ - Creates a context manager which can be used to add the iris gallery - to the PYTHONPATH. The gallery entries are only importable throughout the lifetime - of this context manager. - - """ - orig_sys_path = sys.path - sys.path = sys.path[:] - sys.path += GALLERY_DIRECTORIES - yield - sys.path = orig_sys_path - @contextlib.contextmanager def show_replaced_by_check_graphic(test_id): @@ -71,27 +43,6 @@ def replacement_show(): plt.show = iplt.show = qplt.show = orig_show -@contextlib.contextmanager -def fail_any_deprecation_warnings(): - """ - Create a context in which any deprecation warning will cause an error. - - The context also resets all the iris.FUTURE settings to the defaults, as - otherwise changes made in one test can affect subsequent ones. - - """ - with warnings.catch_warnings(): - # Detect and error all and any Iris deprecation warnings. - warnings.simplefilter("error", IrisDeprecation) - # Run with all default settings in iris.FUTURE. - default_future_kwargs = iris.Future().__dict__.copy() - for dead_option in iris.Future.deprecated_options: - # Avoid a warning when setting these ! - del default_future_kwargs[dead_option] - with iris.FUTURE.context(**default_future_kwargs): - yield - - def gallery_examples(): """Generator to yield all current gallery examples.""" current_dir = pathlib.Path(__file__).resolve() diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index ab0cb183b0..7fea112c6a 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -8,29 +8,13 @@ import pytest -# Import Iris tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -from .gallerytest_util import ( - add_gallery_to_path, - fail_any_deprecation_warnings, - gallery_examples, - show_replaced_by_check_graphic, -) +from .gallerytest_util import gallery_examples, show_replaced_by_check_graphic @pytest.mark.parametrize("example_code", gallery_examples()) -def test_plot_example(example_code): - with fail_any_deprecation_warnings(): - with add_gallery_to_path(): - module = importlib.import_module(example_code) - print(module.__file__) - with show_replaced_by_check_graphic( - f"gallery_tests.test_{example_code}" - ): - module.main() - - -if __name__ == "__main__": - tests.main() +def test_plot_example( + example_code, add_gallery_to_path, fail_any_deprecation_warnings +): + module = importlib.import_module(example_code) + with show_replaced_by_check_graphic(f"gallery_tests.test_{example_code}"): + module.main() From b6d968b6d77dc0de97dc6c702c9847051350f980 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 14 Jun 2022 17:12:58 +0100 Subject: [PATCH 03/23] use pathlib instead of os --- docs/gallery_tests/conftest.py | 10 ++++------ docs/gallery_tests/gallerytest_util.py | 10 +++++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index eacd0f9b55..82da0b034d 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -10,7 +10,6 @@ """ -import os.path import sys import warnings @@ -19,12 +18,11 @@ import iris from iris._deprecation import IrisDeprecation -GALLERY_DIRECTORY = os.path.join( - os.path.dirname(os.path.dirname(__file__)), "gallery_code" -) +from .gallerytest_util import gallery_path + +GALLERY_DIRECTORY = gallery_path() GALLERY_DIRECTORIES = [ - os.path.join(GALLERY_DIRECTORY, the_dir) - for the_dir in os.listdir(GALLERY_DIRECTORY) + str(path) for path in GALLERY_DIRECTORY.iterdir() if path.is_dir() ] diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index 5d101e82fb..421155eb1c 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -43,9 +43,13 @@ def replacement_show(): plt.show = iplt.show = qplt.show = orig_show +def gallery_path(): + """Return path to gallery code.""" + current_dir = pathlib.Path(__file__).resolve() + return current_dir.parents[1] / "gallery_code" + + def gallery_examples(): """Generator to yield all current gallery examples.""" - current_dir = pathlib.Path(__file__).resolve() - code_dir = current_dir.parents[1] / "gallery_code" - for example_file in code_dir.glob("*/plot*.py"): + for example_file in gallery_path().glob("*/plot*.py"): yield example_file.stem From 7a92f4ea8e5b838fbef415c259890f4c2eb4dc38 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 14 Jun 2022 17:15:48 +0100 Subject: [PATCH 04/23] docstrings --- docs/gallery_tests/conftest.py | 3 +-- docs/gallery_tests/gallerytest_util.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 82da0b034d..6f4eb5f4ac 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -5,8 +5,7 @@ # licensing details. """ -Provides context managers which are fundamental to the ability -to run the gallery tests. +Pytest fixtures for the gallery tests. """ diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index 421155eb1c..1de980ddd7 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -5,7 +5,7 @@ # licensing details. """ -Provides context managers which are fundamental to the ability +Provides context manager and utility functions which are fundamental to the ability to run the gallery tests. """ From 00066583313d69f7ba37d1bb38e6ff440bead29b Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 14 Jun 2022 17:33:47 +0100 Subject: [PATCH 05/23] use pytest.mark.filterwarnings --- docs/gallery_tests/conftest.py | 27 ++++++++------------- docs/gallery_tests/test_gallery_examples.py | 5 ++-- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 6f4eb5f4ac..106fa67f8e 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -10,12 +10,10 @@ """ import sys -import warnings import pytest import iris -from iris._deprecation import IrisDeprecation from .gallerytest_util import gallery_path @@ -41,21 +39,16 @@ def add_gallery_to_path(): @pytest.fixture -def fail_any_deprecation_warnings(): +def iris_future_defaults(): """ - Create a fixture in which any deprecation warning will cause an error. - - The context also resets all the iris.FUTURE settings to the defaults, as - otherwise changes made in one test can affect subsequent ones. + Create a fixture which resets all the iris.FUTURE settings to the defaults, + as otherwise changes made in one test can affect subsequent ones. """ - with warnings.catch_warnings(): - # Detect and error all and any Iris deprecation warnings. - warnings.simplefilter("error", IrisDeprecation) - # Run with all default settings in iris.FUTURE. - default_future_kwargs = iris.Future().__dict__.copy() - for dead_option in iris.Future.deprecated_options: - # Avoid a warning when setting these ! - del default_future_kwargs[dead_option] - with iris.FUTURE.context(**default_future_kwargs): - yield + # Run with all default settings in iris.FUTURE. + default_future_kwargs = iris.Future().__dict__.copy() + for dead_option in iris.Future.deprecated_options: + # Avoid a warning when setting these ! + del default_future_kwargs[dead_option] + with iris.FUTURE.context(**default_future_kwargs): + yield diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index 7fea112c6a..c68c0f308c 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -11,10 +11,9 @@ from .gallerytest_util import gallery_examples, show_replaced_by_check_graphic +@pytest.mark.filterwarnings("error::iris.IrisDeprecation") @pytest.mark.parametrize("example_code", gallery_examples()) -def test_plot_example( - example_code, add_gallery_to_path, fail_any_deprecation_warnings -): +def test_plot_example(example_code, add_gallery_to_path, iris_future_defaults): module = importlib.import_module(example_code) with show_replaced_by_check_graphic(f"gallery_tests.test_{example_code}"): module.main() From f4607e340506268ff3cc278b86701651a8dd7f78 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 15 Jun 2022 11:25:49 +0100 Subject: [PATCH 06/23] show_replaced_by_check_graphic as fixture --- docs/gallery_tests/conftest.py | 33 +++++++++++++++++++-- docs/gallery_tests/gallerytest_util.py | 31 +------------------ docs/gallery_tests/test_gallery_examples.py | 12 ++++---- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 106fa67f8e..d6e87d7b48 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -8,14 +8,18 @@ Pytest fixtures for the gallery tests. """ - +import collections import sys +import matplotlib.pyplot as plt import pytest import iris +import iris.plot as iplt +import iris.quickplot as qplt +from iris.tests import check_graphic -from .gallerytest_util import gallery_path +from .gallerytest_util import gallery_examples, gallery_path GALLERY_DIRECTORY = gallery_path() GALLERY_DIRECTORIES = [ @@ -52,3 +56,28 @@ def iris_future_defaults(): del default_future_kwargs[dead_option] with iris.FUTURE.context(**default_future_kwargs): yield + + +@pytest.fixture(params=gallery_examples()) +def show_replaced_by_check_graphic(request): + """ + Creates a fixture which, for the gallery examples specified by params, is + used to replace the functionality of matplotlib.pyplot.show with a function + which calls the check_graphic function (iris.tests.check_graphic). + + Yields the example name so it can be imported in the test. + + """ + test_id = f"gallery_tests.test_{request.param}" + assertion_counts = collections.defaultdict(int) + + def replacement_show(): + # form a closure on test_case and tolerance + unique_id = f"{test_id}.{assertion_counts[test_id]}" + assertion_counts[test_id] += 1 + check_graphic(unique_id) + + orig_show = plt.show + plt.show = iplt.show = qplt.show = replacement_show + yield request.param + plt.show = iplt.show = qplt.show = orig_show diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index 1de980ddd7..30c78c0ac6 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -10,37 +10,8 @@ """ -import collections -import contextlib -import pathlib - -import matplotlib.pyplot as plt - -import iris.plot as iplt -import iris.quickplot as qplt -from iris.tests import check_graphic - -@contextlib.contextmanager -def show_replaced_by_check_graphic(test_id): - """ - Creates a context manager which can be used to replace the functionality - of matplotlib.pyplot.show with a function which calls the check_graphic - function (iris.tests.check_graphic). - - """ - assertion_counts = collections.defaultdict(int) - - def replacement_show(): - # form a closure on test_case and tolerance - unique_id = f"{test_id}.{assertion_counts[test_id]}" - assertion_counts[test_id] += 1 - check_graphic(unique_id) - - orig_show = plt.show - plt.show = iplt.show = qplt.show = replacement_show - yield - plt.show = iplt.show = qplt.show = orig_show +import pathlib def gallery_path(): diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index c68c0f308c..deef100365 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -8,12 +8,10 @@ import pytest -from .gallerytest_util import gallery_examples, show_replaced_by_check_graphic - @pytest.mark.filterwarnings("error::iris.IrisDeprecation") -@pytest.mark.parametrize("example_code", gallery_examples()) -def test_plot_example(example_code, add_gallery_to_path, iris_future_defaults): - module = importlib.import_module(example_code) - with show_replaced_by_check_graphic(f"gallery_tests.test_{example_code}"): - module.main() +def test_plot_example( + add_gallery_to_path, iris_future_defaults, show_replaced_by_check_graphic +): + module = importlib.import_module(show_replaced_by_check_graphic) + module.main() From 4e1adc97383e2575a2fb34534e3c5c57e22c979c Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 15 Jun 2022 11:28:41 +0100 Subject: [PATCH 07/23] Revert previous (more readable without) This reverts commit bdca27cd301fff9de034f14db9da991dac43facf. --- docs/gallery_tests/conftest.py | 33 ++------------------- docs/gallery_tests/gallerytest_util.py | 31 ++++++++++++++++++- docs/gallery_tests/test_gallery_examples.py | 12 ++++---- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index d6e87d7b48..106fa67f8e 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -8,18 +8,14 @@ Pytest fixtures for the gallery tests. """ -import collections + import sys -import matplotlib.pyplot as plt import pytest import iris -import iris.plot as iplt -import iris.quickplot as qplt -from iris.tests import check_graphic -from .gallerytest_util import gallery_examples, gallery_path +from .gallerytest_util import gallery_path GALLERY_DIRECTORY = gallery_path() GALLERY_DIRECTORIES = [ @@ -56,28 +52,3 @@ def iris_future_defaults(): del default_future_kwargs[dead_option] with iris.FUTURE.context(**default_future_kwargs): yield - - -@pytest.fixture(params=gallery_examples()) -def show_replaced_by_check_graphic(request): - """ - Creates a fixture which, for the gallery examples specified by params, is - used to replace the functionality of matplotlib.pyplot.show with a function - which calls the check_graphic function (iris.tests.check_graphic). - - Yields the example name so it can be imported in the test. - - """ - test_id = f"gallery_tests.test_{request.param}" - assertion_counts = collections.defaultdict(int) - - def replacement_show(): - # form a closure on test_case and tolerance - unique_id = f"{test_id}.{assertion_counts[test_id]}" - assertion_counts[test_id] += 1 - check_graphic(unique_id) - - orig_show = plt.show - plt.show = iplt.show = qplt.show = replacement_show - yield request.param - plt.show = iplt.show = qplt.show = orig_show diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index 30c78c0ac6..1de980ddd7 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -10,9 +10,38 @@ """ - +import collections +import contextlib import pathlib +import matplotlib.pyplot as plt + +import iris.plot as iplt +import iris.quickplot as qplt +from iris.tests import check_graphic + + +@contextlib.contextmanager +def show_replaced_by_check_graphic(test_id): + """ + Creates a context manager which can be used to replace the functionality + of matplotlib.pyplot.show with a function which calls the check_graphic + function (iris.tests.check_graphic). + + """ + assertion_counts = collections.defaultdict(int) + + def replacement_show(): + # form a closure on test_case and tolerance + unique_id = f"{test_id}.{assertion_counts[test_id]}" + assertion_counts[test_id] += 1 + check_graphic(unique_id) + + orig_show = plt.show + plt.show = iplt.show = qplt.show = replacement_show + yield + plt.show = iplt.show = qplt.show = orig_show + def gallery_path(): """Return path to gallery code.""" diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index deef100365..c68c0f308c 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -8,10 +8,12 @@ import pytest +from .gallerytest_util import gallery_examples, show_replaced_by_check_graphic + @pytest.mark.filterwarnings("error::iris.IrisDeprecation") -def test_plot_example( - add_gallery_to_path, iris_future_defaults, show_replaced_by_check_graphic -): - module = importlib.import_module(show_replaced_by_check_graphic) - module.main() +@pytest.mark.parametrize("example_code", gallery_examples()) +def test_plot_example(example_code, add_gallery_to_path, iris_future_defaults): + module = importlib.import_module(example_code) + with show_replaced_by_check_graphic(f"gallery_tests.test_{example_code}"): + module.main() From 7c3f4d3eb41ec02bea61e8a5158e947ed66ebdc6 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 15 Jun 2022 11:39:27 +0100 Subject: [PATCH 08/23] gallery_dir function to variable --- docs/gallery_tests/conftest.py | 5 ++--- docs/gallery_tests/gallerytest_util.py | 23 ++++++++++------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 106fa67f8e..55d2e6b5bd 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -15,11 +15,10 @@ import iris -from .gallerytest_util import gallery_path +from .gallerytest_util import GALLERY_DIR -GALLERY_DIRECTORY = gallery_path() GALLERY_DIRECTORIES = [ - str(path) for path in GALLERY_DIRECTORY.iterdir() if path.is_dir() + str(path) for path in GALLERY_DIR.iterdir() if path.is_dir() ] diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index 1de980ddd7..44c938ee1d 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -5,7 +5,7 @@ # licensing details. """ -Provides context manager and utility functions which are fundamental to the ability +Provides context manager and generator which are fundamental to the ability to run the gallery tests. """ @@ -20,6 +20,15 @@ import iris.quickplot as qplt from iris.tests import check_graphic +CURRENT_DIR = pathlib.Path(__file__).resolve() +GALLERY_DIR = CURRENT_DIR.parents[1] / "gallery_code" + + +def gallery_examples(): + """Generator to yield all current gallery examples.""" + for example_file in GALLERY_DIR.glob("*/plot*.py"): + yield example_file.stem + @contextlib.contextmanager def show_replaced_by_check_graphic(test_id): @@ -41,15 +50,3 @@ def replacement_show(): plt.show = iplt.show = qplt.show = replacement_show yield plt.show = iplt.show = qplt.show = orig_show - - -def gallery_path(): - """Return path to gallery code.""" - current_dir = pathlib.Path(__file__).resolve() - return current_dir.parents[1] / "gallery_code" - - -def gallery_examples(): - """Generator to yield all current gallery examples.""" - for example_file in gallery_path().glob("*/plot*.py"): - yield example_file.stem From 81da16dc7e465c20ebb3ead2b39a1a53460cf9eb Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 15 Jun 2022 13:31:48 +0100 Subject: [PATCH 09/23] add setup/teardown fixture --- docs/gallery_code/general/plot_cross_section.py | 3 +++ docs/gallery_tests/conftest.py | 15 +++++++++++++++ docs/gallery_tests/test_gallery_examples.py | 7 ++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/gallery_code/general/plot_cross_section.py b/docs/gallery_code/general/plot_cross_section.py index 12f4bdb0dc..9c39759c4d 100644 --- a/docs/gallery_code/general/plot_cross_section.py +++ b/docs/gallery_code/general/plot_cross_section.py @@ -29,6 +29,9 @@ def main(): qplt.contourf( cross_section, coords=["grid_longitude", "altitude"], cmap="RdBu_r" ) + + assert False + iplt.show() # Now do the equivalent plot, only against model level diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 55d2e6b5bd..71adbd1526 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -11,6 +11,7 @@ import sys +import matplotlib.pyplot as plt import pytest import iris @@ -37,6 +38,20 @@ def add_gallery_to_path(): sys.path = orig_sys_path +@pytest.fixture +def image_setup_teardown(): + """ + Setup and teardown fixture. + + Ensures all figures are closed before and after test to prevent one test + polluting another if it fails badly. + + """ + plt.close("all") + yield + plt.close("all") + + @pytest.fixture def iris_future_defaults(): """ diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index c68c0f308c..a37f5af764 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -13,7 +13,12 @@ @pytest.mark.filterwarnings("error::iris.IrisDeprecation") @pytest.mark.parametrize("example_code", gallery_examples()) -def test_plot_example(example_code, add_gallery_to_path, iris_future_defaults): +def test_plot_example( + example_code, + add_gallery_to_path, + image_setup_teardown, + iris_future_defaults, +): module = importlib.import_module(example_code) with show_replaced_by_check_graphic(f"gallery_tests.test_{example_code}"): module.main() From 273075f05e8e440e3e8e25b8602b4a46fb9338f0 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 15 Jun 2022 13:35:07 +0100 Subject: [PATCH 10/23] tweak docstring --- docs/gallery_tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 71adbd1526..a29b784a7a 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -28,7 +28,7 @@ def add_gallery_to_path(): """ Creates a fixture which can be used to add the iris gallery to the PYTHONPATH. The gallery entries are only importable throughout the lifetime - of this context manager. + of the test. """ orig_sys_path = sys.path From 19bca6c6e9cbd87daa8e3b03ca238f67c652b971 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 15 Jun 2022 15:43:21 +0100 Subject: [PATCH 11/23] remove gallerytests from Makefile --- docs/Makefile | 5 ----- docs/gallery_tests/conftest.py | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 44c89206d2..f4c8d0b7f4 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -55,8 +55,3 @@ linkcheck: echo "Running linkcheck in $$i..."; \ (cd $$i; $(MAKE) $(MFLAGS) $(MYMAKEFLAGS) linkcheck); done -gallerytest: - @echo - @echo "Running \"gallery\" tests..." - @echo - python -m unittest discover -v -t . diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index a29b784a7a..1b84398c69 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -44,7 +44,7 @@ def image_setup_teardown(): Setup and teardown fixture. Ensures all figures are closed before and after test to prevent one test - polluting another if it fails badly. + polluting another if it fails with a figure unclosed. """ plt.close("all") From 6391ebf24d440b34253b26a9012292758887aaa6 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 15 Jun 2022 16:06:22 +0100 Subject: [PATCH 12/23] update dev guide --- .../contributing_documentation_full.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/src/developers_guide/contributing_documentation_full.rst b/docs/src/developers_guide/contributing_documentation_full.rst index a98ff0a7e9..138b65c704 100755 --- a/docs/src/developers_guide/contributing_documentation_full.rst +++ b/docs/src/developers_guide/contributing_documentation_full.rst @@ -72,14 +72,20 @@ This is useful for a final test before committing your changes. Testing ~~~~~~~ -There are a ways to test various aspects of the documentation. The -``make`` commands shown below can be run in the ``docs`` or -``docs/src`` directory. +There are a ways to test various aspects of the documentation. Each :ref:`contributing.documentation.gallery` entry has a corresponding test. To run the tests:: - make gallerytest + pytest -v docs/gallery_tests/test_gallery_examples.py + +To run a test for a single gallery example, use the ``pytest -k`` option for +pattern matching, e.g.:: + + pytest -v -k plot_coriolis docs/gallery_tests/test_gallery_examples.py + +The ``make`` commands shown below can be run in the ``docs`` or ``docs/src`` +directory. Many documentation pages includes python code itself that can be run to ensure it is still valid or to demonstrate examples. To ensure these tests pass From d50a8a7051d98f611a4250748d49da75bec94f94 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Thu, 16 Jun 2022 11:10:45 +0100 Subject: [PATCH 13/23] doc tweaks --- docs/gallery_tests/conftest.py | 5 +---- .../src/developers_guide/contributing_documentation_full.rst | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 1b84398c69..304c4ed9a3 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -4,10 +4,7 @@ # See COPYING and COPYING.LESSER in the root of the repository for full # licensing details. -""" -Pytest fixtures for the gallery tests. - -""" +"""Pytest fixtures for the gallery tests.""" import sys diff --git a/docs/src/developers_guide/contributing_documentation_full.rst b/docs/src/developers_guide/contributing_documentation_full.rst index 138b65c704..ac62a67373 100755 --- a/docs/src/developers_guide/contributing_documentation_full.rst +++ b/docs/src/developers_guide/contributing_documentation_full.rst @@ -72,10 +72,10 @@ This is useful for a final test before committing your changes. Testing ~~~~~~~ -There are a ways to test various aspects of the documentation. +There are various ways to test aspects of the documentation. Each :ref:`contributing.documentation.gallery` entry has a corresponding test. -To run the tests:: +To run all the gallery tests:: pytest -v docs/gallery_tests/test_gallery_examples.py From 8e04536b5ccf5b5c2d9072917a94a65e265bb45d Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 17 Jun 2022 09:58:20 +0100 Subject: [PATCH 14/23] use monkeypatch to simplify --- docs/gallery_tests/gallerytest_util.py | 30 --------------------- docs/gallery_tests/test_gallery_examples.py | 19 ++++++++++--- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py index 44c938ee1d..203ccfbcc7 100644 --- a/docs/gallery_tests/gallerytest_util.py +++ b/docs/gallery_tests/gallerytest_util.py @@ -10,16 +10,8 @@ """ -import collections -import contextlib import pathlib -import matplotlib.pyplot as plt - -import iris.plot as iplt -import iris.quickplot as qplt -from iris.tests import check_graphic - CURRENT_DIR = pathlib.Path(__file__).resolve() GALLERY_DIR = CURRENT_DIR.parents[1] / "gallery_code" @@ -28,25 +20,3 @@ def gallery_examples(): """Generator to yield all current gallery examples.""" for example_file in GALLERY_DIR.glob("*/plot*.py"): yield example_file.stem - - -@contextlib.contextmanager -def show_replaced_by_check_graphic(test_id): - """ - Creates a context manager which can be used to replace the functionality - of matplotlib.pyplot.show with a function which calls the check_graphic - function (iris.tests.check_graphic). - - """ - assertion_counts = collections.defaultdict(int) - - def replacement_show(): - # form a closure on test_case and tolerance - unique_id = f"{test_id}.{assertion_counts[test_id]}" - assertion_counts[test_id] += 1 - check_graphic(unique_id) - - orig_show = plt.show - plt.show = iplt.show = qplt.show = replacement_show - yield - plt.show = iplt.show = qplt.show = orig_show diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index a37f5af764..588c80ce8f 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -6,9 +6,12 @@ import importlib +import matplotlib.pyplot as plt import pytest -from .gallerytest_util import gallery_examples, show_replaced_by_check_graphic +from iris.tests import check_graphic + +from .gallerytest_util import gallery_examples @pytest.mark.filterwarnings("error::iris.IrisDeprecation") @@ -18,7 +21,17 @@ def test_plot_example( add_gallery_to_path, image_setup_teardown, iris_future_defaults, + monkeypatch, ): + def no_show(): + pass + + monkeypatch.setattr(plt, "show", no_show) + module = importlib.import_module(example_code) - with show_replaced_by_check_graphic(f"gallery_tests.test_{example_code}"): - module.main() + + module.main() + for fig_num in plt.get_fignums(): + plt.figure(fig_num) + image_id = f"gallery_tests.test_{example_code}.{fig_num - 1}" + check_graphic(image_id) From b16979d48854a33f5ca1553c50823ae6a29aeeae Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 17 Jun 2022 10:35:11 +0100 Subject: [PATCH 15/23] move stuff about --- docs/gallery_tests/conftest.py | 5 +++-- docs/gallery_tests/gallerytest_util.py | 22 --------------------- docs/gallery_tests/test_gallery_examples.py | 8 +++++++- 3 files changed, 10 insertions(+), 25 deletions(-) delete mode 100644 docs/gallery_tests/gallerytest_util.py diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 304c4ed9a3..bf73f7c391 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -6,6 +6,7 @@ """Pytest fixtures for the gallery tests.""" +import pathlib import sys import matplotlib.pyplot as plt @@ -13,8 +14,8 @@ import iris -from .gallerytest_util import GALLERY_DIR - +CURRENT_DIR = pathlib.Path(__file__).resolve() +GALLERY_DIR = CURRENT_DIR.parents[1] / "gallery_code" GALLERY_DIRECTORIES = [ str(path) for path in GALLERY_DIR.iterdir() if path.is_dir() ] diff --git a/docs/gallery_tests/gallerytest_util.py b/docs/gallery_tests/gallerytest_util.py deleted file mode 100644 index 203ccfbcc7..0000000000 --- a/docs/gallery_tests/gallerytest_util.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright Iris contributors -# -# This file is part of Iris and is released under the LGPL license. -# See COPYING and COPYING.LESSER in the root of the repository for full -# licensing details. - -""" -Provides context manager and generator which are fundamental to the ability -to run the gallery tests. - -""" - -import pathlib - -CURRENT_DIR = pathlib.Path(__file__).resolve() -GALLERY_DIR = CURRENT_DIR.parents[1] / "gallery_code" - - -def gallery_examples(): - """Generator to yield all current gallery examples.""" - for example_file in GALLERY_DIR.glob("*/plot*.py"): - yield example_file.stem diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index 588c80ce8f..77eb6e5aee 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -11,7 +11,13 @@ from iris.tests import check_graphic -from .gallerytest_util import gallery_examples +from .conftest import GALLERY_DIR + + +def gallery_examples(): + """Generator to yield all current gallery examples.""" + for example_file in GALLERY_DIR.glob("*/plot*.py"): + yield example_file.stem @pytest.mark.filterwarnings("error::iris.IrisDeprecation") From 3c744b2df2de204153cc195d99c62b9fc708c10c Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 17 Jun 2022 11:23:48 +0100 Subject: [PATCH 16/23] monkeypatch for sys.path; comments and param ids --- docs/gallery_tests/conftest.py | 23 --------------- docs/gallery_tests/test_gallery_examples.py | 31 +++++++++++++++------ 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index bf73f7c391..1542d32d5e 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -6,35 +6,12 @@ """Pytest fixtures for the gallery tests.""" -import pathlib -import sys import matplotlib.pyplot as plt import pytest import iris -CURRENT_DIR = pathlib.Path(__file__).resolve() -GALLERY_DIR = CURRENT_DIR.parents[1] / "gallery_code" -GALLERY_DIRECTORIES = [ - str(path) for path in GALLERY_DIR.iterdir() if path.is_dir() -] - - -@pytest.fixture -def add_gallery_to_path(): - """ - Creates a fixture which can be used to add the iris gallery to the - PYTHONPATH. The gallery entries are only importable throughout the lifetime - of the test. - - """ - orig_sys_path = sys.path - sys.path = sys.path[:] - sys.path += GALLERY_DIRECTORIES - yield - sys.path = orig_sys_path - @pytest.fixture def image_setup_teardown(): diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index 77eb6e5aee..276d1828d7 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -5,38 +5,53 @@ # licensing details. import importlib +import pathlib import matplotlib.pyplot as plt import pytest from iris.tests import check_graphic -from .conftest import GALLERY_DIR - def gallery_examples(): - """Generator to yield all current gallery examples.""" - for example_file in GALLERY_DIR.glob("*/plot*.py"): - yield example_file.stem + """ + Generator to yield all current gallery examples and their containing + directories. + + """ + current_dir = pathlib.Path(__file__).resolve() + gallery_dir = current_dir.parents[1] / "gallery_code" + for example_file in gallery_dir.glob("*/plot*.py"): + yield example_file.parent, example_file.stem @pytest.mark.filterwarnings("error::iris.IrisDeprecation") -@pytest.mark.parametrize("example_code", gallery_examples()) +@pytest.mark.parametrize("example", gallery_examples(), ids=lambda arg: arg[1]) def test_plot_example( - example_code, - add_gallery_to_path, + example, image_setup_teardown, iris_future_defaults, monkeypatch, ): + """Test that all figures from example code match KGO.""" + + example_dir, example_code = example + + # Replace pyplot.show with a function that does nothing, so all figures from the + # example are still open after it runs. def no_show(): pass monkeypatch.setattr(plt, "show", no_show) + # Add example code to sys.path and import it. + monkeypatch.syspath_prepend(example_dir) module = importlib.import_module(example_code) + # Run example. module.main() + # Loop through open figures and set each to be the current figure so check_graphic + # will find it. for fig_num in plt.get_fignums(): plt.figure(fig_num) image_id = f"gallery_tests.test_{example_code}.{fig_num - 1}" From 3778b28c592d70c7efd99727522ec25cf667a8c5 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 17 Jun 2022 13:11:31 +0100 Subject: [PATCH 17/23] revert assert False --- docs/gallery_code/general/plot_cross_section.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/gallery_code/general/plot_cross_section.py b/docs/gallery_code/general/plot_cross_section.py index 9c39759c4d..12f4bdb0dc 100644 --- a/docs/gallery_code/general/plot_cross_section.py +++ b/docs/gallery_code/general/plot_cross_section.py @@ -29,9 +29,6 @@ def main(): qplt.contourf( cross_section, coords=["grid_longitude", "altitude"], cmap="RdBu_r" ) - - assert False - iplt.show() # Now do the equivalent plot, only against model level From efb9901ef70a313a7000f0465f4fce34625c2c1c Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 17 Jun 2022 13:29:58 +0100 Subject: [PATCH 18/23] revert deliberate fails --- docs/gallery_code/general/plot_inset.py | 2 +- docs/gallery_code/meteorology/plot_hovmoller.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/gallery_code/general/plot_inset.py b/docs/gallery_code/general/plot_inset.py index c0d3827d55..004d01bc6f 100644 --- a/docs/gallery_code/general/plot_inset.py +++ b/docs/gallery_code/general/plot_inset.py @@ -56,7 +56,7 @@ def main(): # Manually set the orientation and tick marks on your colour bar ticklist = np.linspace(np.min(region.data), np.max(region.data), 4) plt.colorbar(orientation="horizontal", ticks=ticklist) - ax_sub.set_title("Data Region", color="r") + ax_sub.set_title("Data Region") # Add coastlines ax_sub.coastlines() # request to show entire map, using the colour mesh on the data region only diff --git a/docs/gallery_code/meteorology/plot_hovmoller.py b/docs/gallery_code/meteorology/plot_hovmoller.py index 2269086dd5..e9f8207a94 100644 --- a/docs/gallery_code/meteorology/plot_hovmoller.py +++ b/docs/gallery_code/meteorology/plot_hovmoller.py @@ -15,12 +15,9 @@ import iris import iris.plot as iplt import iris.quickplot as qplt -import iris.util def main(): - iris.util.approx_equal(3, 4) - # load a single cube of surface temperature between +/- 5 latitude fname = iris.sample_data_path("ostia_monthly.nc") cube = iris.load_cube( From 2b2b75af6ff428bfb6722dcf8678a59cf659476e Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Mon, 20 Jun 2022 17:14:30 +0100 Subject: [PATCH 19/23] import_patches fixture --- docs/gallery_tests/conftest.py | 24 +++++++++++++++ docs/gallery_tests/test_gallery_examples.py | 33 ++++++--------------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/docs/gallery_tests/conftest.py b/docs/gallery_tests/conftest.py index 1542d32d5e..a218b305a2 100644 --- a/docs/gallery_tests/conftest.py +++ b/docs/gallery_tests/conftest.py @@ -6,12 +6,16 @@ """Pytest fixtures for the gallery tests.""" +import pathlib import matplotlib.pyplot as plt import pytest import iris +CURRENT_DIR = pathlib.Path(__file__).resolve() +GALLERY_DIR = CURRENT_DIR.parents[1] / "gallery_code" + @pytest.fixture def image_setup_teardown(): @@ -27,6 +31,26 @@ def image_setup_teardown(): plt.close("all") +@pytest.fixture +def import_patches(monkeypatch): + """ + Replace plt.show() with a function that does nothing, also add all the + gallery examples to sys.path. + + """ + + def no_show(): + pass + + monkeypatch.setattr(plt, "show", no_show) + + for example_dir in GALLERY_DIR.iterdir(): + if example_dir.is_dir(): + monkeypatch.syspath_prepend(example_dir) + + yield + + @pytest.fixture def iris_future_defaults(): """ diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index 276d1828d7..caf833165c 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -5,48 +5,33 @@ # licensing details. import importlib -import pathlib import matplotlib.pyplot as plt import pytest from iris.tests import check_graphic +from .conftest import GALLERY_DIR + def gallery_examples(): - """ - Generator to yield all current gallery examples and their containing - directories. + """Generator to yield all current gallery examples.""" - """ - current_dir = pathlib.Path(__file__).resolve() - gallery_dir = current_dir.parents[1] / "gallery_code" - for example_file in gallery_dir.glob("*/plot*.py"): - yield example_file.parent, example_file.stem + for example_file in GALLERY_DIR.glob("*/plot*.py"): + yield example_file.stem @pytest.mark.filterwarnings("error::iris.IrisDeprecation") -@pytest.mark.parametrize("example", gallery_examples(), ids=lambda arg: arg[1]) +@pytest.mark.parametrize("example", gallery_examples()) def test_plot_example( example, image_setup_teardown, + import_patches, iris_future_defaults, - monkeypatch, ): """Test that all figures from example code match KGO.""" - example_dir, example_code = example - - # Replace pyplot.show with a function that does nothing, so all figures from the - # example are still open after it runs. - def no_show(): - pass - - monkeypatch.setattr(plt, "show", no_show) - - # Add example code to sys.path and import it. - monkeypatch.syspath_prepend(example_dir) - module = importlib.import_module(example_code) + module = importlib.import_module(example) # Run example. module.main() @@ -54,5 +39,5 @@ def no_show(): # will find it. for fig_num in plt.get_fignums(): plt.figure(fig_num) - image_id = f"gallery_tests.test_{example_code}.{fig_num - 1}" + image_id = f"gallery_tests.test_{example}.{fig_num - 1}" check_graphic(image_id) From b30be59447cb47cb540f578f1c4f5ac0c2b44371 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 28 Jun 2022 10:56:27 +0100 Subject: [PATCH 20/23] post rebase check_graphic fix --- docs/gallery_tests/test_gallery_examples.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/gallery_tests/test_gallery_examples.py b/docs/gallery_tests/test_gallery_examples.py index caf833165c..0d0793a7da 100644 --- a/docs/gallery_tests/test_gallery_examples.py +++ b/docs/gallery_tests/test_gallery_examples.py @@ -9,7 +9,8 @@ import matplotlib.pyplot as plt import pytest -from iris.tests import check_graphic +from iris.tests import _RESULT_PATH +from iris.tests.graphics import check_graphic from .conftest import GALLERY_DIR @@ -40,4 +41,4 @@ def test_plot_example( for fig_num in plt.get_fignums(): plt.figure(fig_num) image_id = f"gallery_tests.test_{example}.{fig_num - 1}" - check_graphic(image_id) + check_graphic(image_id, _RESULT_PATH) From ff97ca324a1b7e1293bd242ba3f4763f3509c76d Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Tue, 28 Jun 2022 11:00:26 +0100 Subject: [PATCH 21/23] update test references --- lib/iris/tests/results/imagerepo.json | 70 +++++++++++++-------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/lib/iris/tests/results/imagerepo.json b/lib/iris/tests/results/imagerepo.json index 28d6f0bb03..342428ca67 100644 --- a/lib/iris/tests/results/imagerepo.json +++ b/lib/iris/tests/results/imagerepo.json @@ -1,39 +1,39 @@ { - "gallery_tests.test_plot_COP_1d.TestCOP1DPlot.test_plot_COP_1d.0": "aefec91c3601249cc9b3336dc4c8cdb31a64c6d997b3c0eccb5932d285e42f33", - "gallery_tests.test_plot_COP_maps.TestCOPMaps.test_plot_cop_maps.0": "ea9130db95668524913e6ac168991f0d956e917ec76396b96a853dcf94696935", - "gallery_tests.test_plot_SOI_filtering.TestSOIFiltering.test_plot_soi_filtering.0": "fa56f295c5e0694a3c17a58d95e8da536233da99984c5af4c6739b4a9a444eb4", - "gallery_tests.test_plot_TEC.TestTEC.test_plot_TEC.0": "e5a761b69a589a4bc46f9e48c65c6631ce61d1ce3982c13739b33193c0ee3f8c", - "gallery_tests.test_plot_anomaly_log_colouring.TestAnomalyLogColouring.test_plot_anomaly_log_colouring.0": "ec4464e384a39b13931a9b1c85696da968d5e6e63e26847bdbd399938d3c5a4c", - "gallery_tests.test_plot_atlantic_profiles.TestAtlanticProfiles.test_plot_atlantic_profiles.0": "97c160f462a88f07203ebc77a1e36707e61f4e38d8f3d08a910597fc877cec58", - "gallery_tests.test_plot_atlantic_profiles.TestAtlanticProfiles.test_plot_atlantic_profiles.1": "eeea64dd6ea8cd99991d1322b3741e2684571cd89995b3131f32a4765ee2a1cc", - "gallery_tests.test_plot_coriolis.TestCoriolisPlot.test_plot_coriolis.0": "e68665de9a699659c1fe99a5896965966996c46e3e19c1da3a652669c51e1a26", - "gallery_tests.test_plot_cross_section.TestCrossSection.test_plot_cross_section.0": "ea91b17b9562e4d1609f5a05856e4ca45a52957e5ea5f13b1bca9dc0b17b1ac1", - "gallery_tests.test_plot_cross_section.TestCrossSection.test_plot_cross_section.1": "ea9521fb956a394068931e93e07e4aa5856cc47e4a91957b1ba55bb5b17a3b81", - "gallery_tests.test_plot_custom_aggregation.TestCustomAggregation.test_plot_custom_aggregation.0": "ee816f81917e907eb03ec73f856f7ac198d070186e90811f1be33ee1a57a6e18", - "gallery_tests.test_plot_custom_file_loading.TestCustomFileLoading.test_plot_custom_file_loading.0": "fa81cb47845e34bc932797436cccc8343f11359b73523746c48c72d9d9b34da5", - "gallery_tests.test_plot_deriving_phenomena.TestDerivingPhenomena.test_plot_deriving_phenomena.0": "ec97681793689768943c97e8926669d186e8c33f6c99c32e6b936c83d33e2c98", - "gallery_tests.test_plot_global_map.TestGlobalMap.test_plot_global_map.0": "fb997b958466846ed13e87467a997a898d66d17e2cc9906684696f99d3162e81", - "gallery_tests.test_plot_hovmoller.TestGlobalMap.test_plot_hovmoller.0": "eeb46cb4934b934bc07e974bc14b38949943c0fe3e94c17f6ea46cb4c07b3f00", - "gallery_tests.test_plot_inset.TestInsetPlot.test_plot_inset.0": "ebff6992b50096ad9267dac4d640949294924cdbc95d4b699d29952dcda46ed4", - "gallery_tests.test_plot_lagged_ensemble.TestLaggedEnsemble.test_plot_lagged_ensemble.0": "bbbb31b1c44e64e4b1579b5b917133cecc61f146c414668eb1119b1bb197ce34", - "gallery_tests.test_plot_lagged_ensemble.TestLaggedEnsemble.test_plot_lagged_ensemble.1": "aafec5e9e5e03e099a07e0f86542db879438261ec3b13ce78d8dc65a92d83d89", - "gallery_tests.test_plot_lineplot_with_legend.TestLineplotWithLegend.test_plot_lineplot_with_legend.0": "eafd9e12a5a061e9925ec716de489e9685078ec981b229e70ddb79219cc3768d", - "gallery_tests.test_plot_load_nemo.TestLoadNemo.test_plot_load_nemo.0": "a3ff34e87f0049496d17c4d9c04fc225d256971392db9f1696df0f16cec00736", - "gallery_tests.test_plot_orca_projection.TestOrcaProjection.test_plot_orca_projection.0": "bb11721a87cce5e4cce79e81d19b3b5e1e1cd3783168e07835853485e65e2e1e", - "gallery_tests.test_plot_orca_projection.TestOrcaProjection.test_plot_orca_projection.1": "e58661969e799659c1f719a6c867359a1996c0773649c09c3e612679c07b3f66", - "gallery_tests.test_plot_orca_projection.TestOrcaProjection.test_plot_orca_projection.2": "a58660ce9e739b31c93d1c89c8df33863783e23b3f11c07f2664366cc8ee3cc1", - "gallery_tests.test_plot_orca_projection.TestOrcaProjection.test_plot_orca_projection.3": "be817a8784dea56cec79817a919e338437a5c1e73fa16c726c4a3e816a1c6b1c", - "gallery_tests.test_plot_polar_stereo.TestPolarStereo.test_plot_polar_stereo.0": "ba1e615ec7e097ad961f9cb190f038e091c2c1e73f07c11f6f386b3cc1793e01", - "gallery_tests.test_plot_polynomial_fit.TestPolynomialFit.test_plot_polynomial_fit.0": "aeffcb34d244348be5a2c96c3a4fc6d0c4b69f2d87294ccb9f1a125684cd7c11", - "gallery_tests.test_plot_projections_and_annotations.TestProjectionsAndAnnotations.test_plot_projections_and_annotations.0": "fa854f19851a30e4cc76cd0bb0f932dca7c665b0c93ccb4b4ed19e9c3721b5c8", - "gallery_tests.test_plot_projections_and_annotations.TestProjectionsAndAnnotations.test_plot_projections_and_annotations.1": "e3856d999c389662734331afcd2d5a7184dba592b9b69b64d26dc29954b185b2", - "gallery_tests.test_plot_rotated_pole_mapping.TestRotatedPoleMapping.test_plot_rotated_pole_mapping.0": "ee46607e97a19781c0de1f81d0bb3e241f20c16f3fc0c1fe3d263d33d06f3e80", - "gallery_tests.test_plot_rotated_pole_mapping.TestRotatedPoleMapping.test_plot_rotated_pole_mapping.1": "ea57685f95a886a1c0de9da090be3e2697e1c0ff3f00c17e6b266c17c07f3f00", - "gallery_tests.test_plot_rotated_pole_mapping.TestRotatedPoleMapping.test_plot_rotated_pole_mapping.2": "ea57685f95a886a1c0de9da090be3e2497e1c0ff3f01c17e6b366c17c07b3f00", - "gallery_tests.test_plot_rotated_pole_mapping.TestRotatedPoleMapping.test_plot_rotated_pole_mapping.3": "fa8172c6857ecd38cb3392ce36c564311931d85ec64e9787719a39993c316e66", - "gallery_tests.test_plot_wind_barbs.TestWindBarbs.test_wind_barbs.0": "e9e161e996169316c1fe9e96c29e36739e13c07c3d61c07f39813929c07f3f01", - "gallery_tests.test_plot_wind_speed.TestWindSpeed.test_plot_wind_speed.0": "e9e960e996169306c1fe9e96c29e36739e03c06c3d61c07f3da139e1c07f3f01", - "gallery_tests.test_plot_wind_speed.TestWindSpeed.test_plot_wind_speed.1": "e9e960e996169306c1ee9f96c29e36739653c06c3d61c07f39a139e1c07f3f01", + "gallery_tests.test_plot_COP_1d.0": "aefec91c3601249cc9b3336dc4c8cdb31a64c6d997b3c0eccb5932d285e42f33", + "gallery_tests.test_plot_COP_maps.0": "ea9130db95668524913e6ac168991f0d956e917ec76396b96a853dcf94696935", + "gallery_tests.test_plot_SOI_filtering.0": "fa56f295c5e0694a3c17a58d95e8da536233da99984c5af4c6739b4a9a444eb4", + "gallery_tests.test_plot_TEC.0": "e5a761b69a589a4bc46f9e48c65c6631ce61d1ce3982c13739b33193c0ee3f8c", + "gallery_tests.test_plot_anomaly_log_colouring.0": "ec4464e384a39b13931a9b1c85696da968d5e6e63e26847bdbd399938d3c5a4c", + "gallery_tests.test_plot_atlantic_profiles.0": "97c160f462a88f07203ebc77a1e36707e61f4e38d8f3d08a910597fc877cec58", + "gallery_tests.test_plot_atlantic_profiles.1": "eeea64dd6ea8cd99991d1322b3741e2684571cd89995b3131f32a4765ee2a1cc", + "gallery_tests.test_plot_coriolis.0": "e68665de9a699659c1fe99a5896965966996c46e3e19c1da3a652669c51e1a26", + "gallery_tests.test_plot_cross_section.0": "ea91b17b9562e4d1609f5a05856e4ca45a52957e5ea5f13b1bca9dc0b17b1ac1", + "gallery_tests.test_plot_cross_section.1": "ea9521fb956a394068931e93e07e4aa5856cc47e4a91957b1ba55bb5b17a3b81", + "gallery_tests.test_plot_custom_aggregation.0": "ee816f81917e907eb03ec73f856f7ac198d070186e90811f1be33ee1a57a6e18", + "gallery_tests.test_plot_custom_file_loading.0": "fa81cb47845e34bc932797436cccc8343f11359b73523746c48c72d9d9b34da5", + "gallery_tests.test_plot_deriving_phenomena.0": "ec97681793689768943c97e8926669d186e8c33f6c99c32e6b936c83d33e2c98", + "gallery_tests.test_plot_global_map.0": "fb997b958466846ed13e87467a997a898d66d17e2cc9906684696f99d3162e81", + "gallery_tests.test_plot_hovmoller.0": "eeb46cb4934b934bc07e974bc14b38949943c0fe3e94c17f6ea46cb4c07b3f00", + "gallery_tests.test_plot_inset.0": "ebff6992b50096ad9267dac4d640949294924cdbc95d4b699d29952dcda46ed4", + "gallery_tests.test_plot_lagged_ensemble.0": "bbbb31b1c44e64e4b1579b5b917133cecc61f146c414668eb1119b1bb197ce34", + "gallery_tests.test_plot_lagged_ensemble.1": "aafec5e9e5e03e099a07e0f86542db879438261ec3b13ce78d8dc65a92d83d89", + "gallery_tests.test_plot_lineplot_with_legend.0": "eafd9e12a5a061e9925ec716de489e9685078ec981b229e70ddb79219cc3768d", + "gallery_tests.test_plot_load_nemo.0": "a3ff34e87f0049496d17c4d9c04fc225d256971392db9f1696df0f16cec00736", + "gallery_tests.test_plot_orca_projection.0": "bb11721a87cce5e4cce79e81d19b3b5e1e1cd3783168e07835853485e65e2e1e", + "gallery_tests.test_plot_orca_projection.1": "e58661969e799659c1f719a6c867359a1996c0773649c09c3e612679c07b3f66", + "gallery_tests.test_plot_orca_projection.2": "a58660ce9e739b31c93d1c89c8df33863783e23b3f11c07f2664366cc8ee3cc1", + "gallery_tests.test_plot_orca_projection.3": "be817a8784dea56cec79817a919e338437a5c1e73fa16c726c4a3e816a1c6b1c", + "gallery_tests.test_plot_polar_stereo.0": "ba1e615ec7e097ad961f9cb190f038e091c2c1e73f07c11f6f386b3cc1793e01", + "gallery_tests.test_plot_polynomial_fit.0": "aeffcb34d244348be5a2c96c3a4fc6d0c4b69f2d87294ccb9f1a125684cd7c11", + "gallery_tests.test_plot_projections_and_annotations.0": "fa854f19851a30e4cc76cd0bb0f932dca7c665b0c93ccb4b4ed19e9c3721b5c8", + "gallery_tests.test_plot_projections_and_annotations.1": "e3856d999c389662734331afcd2d5a7184dba592b9b69b64d26dc29954b185b2", + "gallery_tests.test_plot_rotated_pole_mapping.0": "ee46607e97a19781c0de1f81d0bb3e241f20c16f3fc0c1fe3d263d33d06f3e80", + "gallery_tests.test_plot_rotated_pole_mapping.1": "ea57685f95a886a1c0de9da090be3e2697e1c0ff3f00c17e6b266c17c07f3f00", + "gallery_tests.test_plot_rotated_pole_mapping.2": "ea57685f95a886a1c0de9da090be3e2497e1c0ff3f01c17e6b366c17c07b3f00", + "gallery_tests.test_plot_rotated_pole_mapping.3": "fa8172c6857ecd38cb3392ce36c564311931d85ec64e9787719a39993c316e66", + "gallery_tests.test_plot_wind_barbs.0": "e9e161e996169316c1fe9e96c29e36739e13c07c3d61c07f39813929c07f3f01", + "gallery_tests.test_plot_wind_speed.0": "e9e960e996169306c1fe9e96c29e36739e03c06c3d61c07f3da139e1c07f3f01", + "gallery_tests.test_plot_wind_speed.1": "e9e960e996169306c1ee9f96c29e36739653c06c3d61c07f39a139e1c07f3f01", "iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.0": "fe81c17e817e3e81817e3e81857e7a817e81c17e7e81c17e7a81817e817e8c2e", "iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.1": "fe81857e817e7a85817e7a81857e7e817e81917a7e81817e7a81817e817e843e", "iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.2": "be81817ec17e7a81c17e7e81857e3e803e81817a3e81c17e7a81c17ec97e2c2f", From 6a89729075a9fbd7638e72fd69ccbaf64995e8eb Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 27 Jul 2022 17:39:01 +0100 Subject: [PATCH 22/23] whatsnew --- docs/src/whatsnew/latest.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index f64fbe8c8a..411298fc50 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -282,6 +282,10 @@ This document explains the changes made to Iris for this release publishing of ``iris`` PyPI ``sdist`` and binary ``wheels`` as part of our GitHub Continuous-Integration. (:pull:`4849`) +#. `@rcomer`_ and `@wjbenfold`_ (reviewer) used ``pytest`` parametrization to + streamline the gallery test code. (:pull:`4792`) + + .. comment Whatsnew author names (@github name) in alphabetical order. Note that, core dev names are automatically included by the common_links.inc: From b0eb0773de5c9e39fd1271cfe80e326a4b18bd8c Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 27 Jul 2022 17:45:51 +0100 Subject: [PATCH 23/23] test data version --- .github/workflows/benchmark.yml | 2 +- .github/workflows/ci-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 9ebc7a4c45..b197b58e80 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -15,7 +15,7 @@ jobs: env: IRIS_TEST_DATA_LOC_PATH: benchmarks IRIS_TEST_DATA_PATH: benchmarks/iris-test-data - IRIS_TEST_DATA_VERSION: "2.14" + IRIS_TEST_DATA_VERSION: "2.15" # Lets us manually bump the cache to rebuild ENV_CACHE_BUILD: "0" TEST_DATA_CACHE_BUILD: "2" diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 2657e1e42a..aae1ce2970 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -46,7 +46,7 @@ jobs: session: "tests" env: - IRIS_TEST_DATA_VERSION: "2.14" + IRIS_TEST_DATA_VERSION: "2.15" ENV_NAME: "ci-tests" steps: