diff --git a/lib/iris/tests/_shared_utils.py b/lib/iris/tests/_shared_utils.py index 592a642ec7..527f9c0c77 100644 --- a/lib/iris/tests/_shared_utils.py +++ b/lib/iris/tests/_shared_utils.py @@ -926,19 +926,19 @@ class MyGeoTiffTests(test.IrisTest): skip_sample_data = pytest.mark.skipif( not SAMPLE_DATA_AVAILABLE, - ('Test(s) require "iris-sample-data", ' "which is not available."), + reason=('Test(s) require "iris-sample-data", ' "which is not available."), ) skip_nc_time_axis = pytest.mark.skipif( not NC_TIME_AXIS_AVAILABLE, - 'Test(s) require "nc_time_axis", which is not available.', + reason='Test(s) require "nc_time_axis", which is not available.', ) skip_inet = pytest.mark.skipif( not INET_AVAILABLE, - ('Test(s) require an "internet connection", ' "which is not available."), + reason=('Test(s) require an "internet connection", ' "which is not available."), ) diff --git a/lib/iris/tests/unit/plot/__init__.py b/lib/iris/tests/unit/plot/__init__.py index c262d014f3..3438d6884a 100644 --- a/lib/iris/tests/unit/plot/__init__.py +++ b/lib/iris/tests/unit/plot/__init__.py @@ -4,19 +4,18 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the :mod:`iris.plot` module.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip +import pytest from iris.coords import AuxCoord from iris.plot import _broadcast_2d as broadcast +from iris.tests import _shared_utils from iris.tests.stock import lat_lon_cube, simple_2d -@tests.skip_plot -class TestGraphicStringCoord(tests.GraphicsTest): - def setUp(self): - super().setUp() +@_shared_utils.skip_plot +class TestGraphicStringCoord(_shared_utils.GraphicsTest): + @pytest.fixture(autouse=True) + def _setup(self): self.cube = simple_2d(with_bounds=True) self.cube.add_aux_coord(AuxCoord(list("abcd"), long_name="str_coord"), 1) self.lat_lon_cube = lat_lon_cube() @@ -38,7 +37,7 @@ def tick_loc_and_label(self, axis_name, axes=None): labels = [tick.get_text() for tick in axis.get_ticklabels()] return list(zip(locations, labels)) - def assertBoundsTickLabels(self, axis, axes=None): + def assert_bounds_tick_labels(self, axis, axes=None): actual = self.tick_loc_and_label(axis, axes) expected = [ (-1.0, ""), @@ -48,15 +47,15 @@ def assertBoundsTickLabels(self, axis, axes=None): (3.0, "d"), (4.0, ""), ] - self.assertEqual(expected, actual) + assert expected == actual - def assertPointsTickLabels(self, axis, axes=None): + def assert_points_tick_labels(self, axis, axes=None): actual = self.tick_loc_and_label(axis, axes) expected = [(0.0, "a"), (1.0, "b"), (2.0, "c"), (3.0, "d")] - self.assertEqual(expected, actual) + assert expected == actual -@tests.skip_plot +@_shared_utils.skip_plot class MixinCoords: """Mixin class of common plotting tests providing 2-dimensional permutations of coordinates and anonymous dimensions. @@ -64,14 +63,14 @@ class MixinCoords: """ def _check(self, u, v, data=None): - self.assertEqual(self.mpl_patch.call_count, 1) + assert self.mpl_patch.call_count == 1 if data is not None: (actual_u, actual_v, actual_data), _ = self.mpl_patch.call_args - self.assertArrayEqual(actual_data, data) + _shared_utils.assert_array_equal(actual_data, data) else: (actual_u, actual_v), _ = self.mpl_patch.call_args - self.assertArrayEqual(actual_u, u) - self.assertArrayEqual(actual_v, v) + _shared_utils.assert_array_equal(actual_u, u) + _shared_utils.assert_array_equal(actual_v, v) def test_foo_bar(self): self.draw_func(self.cube, coords=("foo", "bar")) diff --git a/lib/iris/tests/unit/plot/_blockplot_common.py b/lib/iris/tests/unit/plot/_blockplot_common.py index 04a7d8866f..a7abd9dd23 100644 --- a/lib/iris/tests/unit/plot/_blockplot_common.py +++ b/lib/iris/tests/unit/plot/_blockplot_common.py @@ -4,13 +4,8 @@ # See LICENSE in the root of the repository for full licensing details. """Common test code for `iris.plot.pcolor` and `iris.plot.pcolormesh`.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - -from unittest import mock - import numpy as np +import pytest from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords @@ -23,11 +18,11 @@ class MixinStringCoordPlot: # and defines "self.blockplot_func()", to return the `iris.plot` function. def test_yaxis_labels(self): self.blockplot_func()(self.cube, coords=("bar", "str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): self.blockplot_func()(self.cube, coords=("str_coord", "bar")) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") def test_xaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -37,7 +32,7 @@ def test_xaxis_labels_with_axes(self): ax.set_xlim(0, 3) self.blockplot_func()(self.cube, coords=("str_coord", "bar"), axes=ax) plt.close(fig) - self.assertPointsTickLabels("xaxis", ax) + self.assert_points_tick_labels("xaxis", ax) def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -47,23 +42,23 @@ def test_yaxis_labels_with_axes(self): ax.set_ylim(0, 3) self.blockplot_func()(self.cube, axes=ax, coords=("bar", "str_coord")) plt.close(fig) - self.assertPointsTickLabels("yaxis", ax) + self.assert_points_tick_labels("yaxis", ax) def test_geoaxes_exception(self): import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) - self.assertRaises(TypeError, self.blockplot_func(), self.lat_lon_cube, axes=ax) + pytest.raises(TypeError, self.blockplot_func(), self.lat_lon_cube, axes=ax) plt.close(fig) class Mixin2dCoordsPlot(MixinCoords): # Mixin for common coordinate tests on pcolor/pcolormesh. # To use, make a class that inherits from this *and* - # :class:`iris.tests.IrisTest`, - # and defines "self.blockplot_func()", to return the `iris.plot` function. - def blockplot_setup(self): + # defines "self.blockplot_func()", to return the `iris.plot` function. + @pytest.fixture(autouse=True) + def _blockplot_setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=True) coord = self.cube.coord("foo") @@ -76,22 +71,21 @@ def blockplot_setup(self): self.dataT = self.data.T self.draw_func = self.blockplot_func() patch_target_name = "matplotlib.pyplot." + self.draw_func.__name__ - self.mpl_patch = self.patch(patch_target_name) + self.mpl_patch = mocker.patch(patch_target_name) class Mixin2dCoordsContigTol: # Mixin for contiguity tolerance argument to pcolor/pcolormesh. # To use, make a class that inherits from this *and* - # :class:`iris.tests.IrisTest`, - # and defines "self.blockplot_func()", to return the `iris.plot` function, + # defines "self.blockplot_func()", to return the `iris.plot` function, # and defines "self.additional_kwargs" for expected extra call args. - def test_contig_tol(self): + def test_contig_tol(self, mocker): # Patch the inner call to ensure contiguity_tolerance is passed. - cube_argument = mock.sentinel.passed_arg - expected_result = mock.sentinel.returned_value - blockplot_patch = self.patch( + cube_argument = mocker.sentinel.passed_arg + expected_result = mocker.sentinel.returned_value + blockplot_patch = mocker.patch( "iris.plot._draw_2d_from_bounds", - mock.Mock(return_value=expected_result), + mocker.Mock(return_value=expected_result), ) # Make the call draw_func = self.blockplot_func() @@ -99,19 +93,12 @@ def test_contig_tol(self): result = draw_func(cube_argument, contiguity_tolerance=0.0123) drawfunc_name = draw_func.__name__ # Check details of the call that was made. - self.assertEqual( - blockplot_patch.call_args_list, - [ - mock.call( - drawfunc_name, - cube_argument, - contiguity_tolerance=0.0123, - **other_kwargs, - ) - ], - ) - self.assertEqual(result, expected_result) - - -if __name__ == "__main__": - tests.main() + assert blockplot_patch.call_args_list == [ + mocker.call( + drawfunc_name, + cube_argument, + contiguity_tolerance=0.0123, + **other_kwargs, + ) + ] + assert result == expected_result diff --git a/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py index 9ec80cbd50..3b23945118 100644 --- a/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py +++ b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py @@ -6,22 +6,18 @@ function. """ -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - -from unittest import mock - import numpy as np import numpy.ma as ma +import pytest from iris.coords import DimCoord from iris.plot import _check_bounds_contiguity_and_mask +from iris.tests import _shared_utils from iris.tests.stock import make_bounds_discontiguous_at_point, sample_2d_latlons -@tests.skip_plot -class Test_check_bounds_contiguity_and_mask(tests.IrisTest): +@_shared_utils.skip_plot +class Test_check_bounds_contiguity_and_mask: def test_1d_not_checked(self): # Test a 1D coordinate, which is not checked as atol is not set. coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [5, 6]]) @@ -51,7 +47,7 @@ def test_1d_discontigous_unmasked(self): "coordinate are not contiguous and data is not masked where " "the discontiguity occurs" ) - with self.assertRaisesRegex(ValueError, msg): + with pytest.raises(ValueError, match=msg): _check_bounds_contiguity_and_mask(coord, data, atol=1e-3) def test_2d_contiguous(self): @@ -60,18 +56,14 @@ def test_2d_contiguous(self): cube = sample_2d_latlons() _check_bounds_contiguity_and_mask(cube.coord("longitude"), cube.data) - def test_2d_contiguous_atol(self): + def test_2d_contiguous_atol(self, mocker): # Check the atol is passed correctly. cube = sample_2d_latlons() - with mock.patch( - "iris.coords.Coord._discontiguity_in_bounds" - ) as discontiguity_check: - # Discontiguity returns two objects that are unpacked in - # `_check_bounds_contiguity_and_mask`. - discontiguity_check.return_value = [True, None] - _check_bounds_contiguity_and_mask( - cube.coord("longitude"), cube.data, atol=1e-3 - ) + discontiguity_check = mocker.patch("iris.coords.Coord._discontiguity_in_bounds") + # Discontiguity returns two objects that are unpacked in + # `_check_bounds_contiguity_and_mask`. + discontiguity_check.return_value = [True, None] + _check_bounds_contiguity_and_mask(cube.coord("longitude"), cube.data, atol=1e-3) discontiguity_check.assert_called_with(atol=1e-3) def test_2d_discontigous_masked(self): @@ -88,9 +80,5 @@ def test_2d_discontigous_unmasked(self): make_bounds_discontiguous_at_point(cube, 3, 4) msg = "coordinate are not contiguous" cube.data[3, 4] = ma.nomask - with self.assertRaisesRegex(ValueError, msg): + with pytest.raises(ValueError, match=msg): _check_bounds_contiguity_and_mask(cube.coord("longitude"), cube.data) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test__check_geostationary_coords_and_convert.py b/lib/iris/tests/unit/plot/test__check_geostationary_coords_and_convert.py index bf724c443c..c881d550df 100644 --- a/lib/iris/tests/unit/plot/test__check_geostationary_coords_and_convert.py +++ b/lib/iris/tests/unit/plot/test__check_geostationary_coords_and_convert.py @@ -6,20 +6,19 @@ function. """ -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - -from unittest.mock import Mock - from cartopy.crs import Geostationary, NearsidePerspective import numpy as np +import pytest from iris.plot import _check_geostationary_coords_and_convert +from iris.tests import _shared_utils + +class Test__check_geostationary_coords_and_convert: + @pytest.fixture(autouse=True) + def _setup(self, mocker): + self.mocker = mocker -class Test__check_geostationary_coords_and_convert(tests.IrisTest): - def setUp(self): geostationary_altitude = 35785831.0 # proj4_params is the one attribute of the Geostationary class that # is needed for the function. @@ -46,7 +45,7 @@ def _test(self, geostationary=True): projection_spec = NearsidePerspective target_tuple = (self.x_original, self.y_original) - projection = Mock(spec=projection_spec) + projection = self.mocker.Mock(spec=projection_spec) projection.proj4_params = self.proj4_params # Projection is looked for within a dictionary called kwargs. kwargs = {"transform": projection} @@ -54,7 +53,7 @@ def _test(self, geostationary=True): x, y = _check_geostationary_coords_and_convert( self.x_original, self.y_original, kwargs ) - self.assertArrayEqual((x, y), target_tuple) + _shared_utils.assert_array_equal((x, y), target_tuple) def test_geostationary_present(self): self._test(geostationary=True) diff --git a/lib/iris/tests/unit/plot/test__fixup_dates.py b/lib/iris/tests/unit/plot/test__fixup_dates.py index d155f30969..4f5b88faab 100644 --- a/lib/iris/tests/unit/plot/test__fixup_dates.py +++ b/lib/iris/tests/unit/plot/test__fixup_dates.py @@ -4,10 +4,6 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot._fixup_dates` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import datetime from cf_units import Unit @@ -15,34 +11,35 @@ from iris.coords import AuxCoord from iris.plot import _fixup_dates +from iris.tests import _shared_utils -class Test(tests.IrisTest): +class Test: def test_standard_calendar(self): unit = Unit("hours since 2000-04-13 00:00:00", calendar="standard") coord = AuxCoord([1, 3, 6], "time", units=unit) result = _fixup_dates(coord, coord.points) - self.assertIsInstance(result[0], datetime.datetime) + assert isinstance(result[0], datetime.datetime) expected = [ datetime.datetime(2000, 4, 13, 1), datetime.datetime(2000, 4, 13, 3), datetime.datetime(2000, 4, 13, 6), ] - self.assertArrayEqual(result, expected) + _shared_utils.assert_array_equal(result, expected) def test_standard_calendar_sub_second(self): unit = Unit("seconds since 2000-04-13 00:00:00", calendar="standard") coord = AuxCoord([1, 1.25, 1.5], "time", units=unit) result = _fixup_dates(coord, coord.points) - self.assertIsInstance(result[0], datetime.datetime) + assert isinstance(result[0], datetime.datetime) expected = [ datetime.datetime(2000, 4, 13, 0, 0, 1), datetime.datetime(2000, 4, 13, 0, 0, 1), datetime.datetime(2000, 4, 13, 0, 0, 2), ] - self.assertArrayEqual(result, expected) + _shared_utils.assert_array_equal(result, expected) - @tests.skip_nc_time_axis + @_shared_utils.skip_nc_time_axis def test_360_day_calendar(self): calendar = "360_day" unit = Unit("days since 2000-02-25 00:00:00", calendar=calendar) @@ -53,9 +50,9 @@ def test_360_day_calendar(self): cftime.datetime(2000, 2, 29, calendar=calendar), cftime.datetime(2000, 2, 30, calendar=calendar), ] - self.assertArrayEqual(result, expected_datetimes) + _shared_utils.assert_array_equal(result, expected_datetimes) - @tests.skip_nc_time_axis + @_shared_utils.skip_nc_time_axis def test_365_day_calendar(self): calendar = "365_day" unit = Unit("minutes since 2000-02-25 00:00:00", calendar=calendar) @@ -66,16 +63,12 @@ def test_365_day_calendar(self): cftime.datetime(2000, 2, 25, 1, 0, calendar=calendar), cftime.datetime(2000, 2, 25, 2, 30, calendar=calendar), ] - self.assertArrayEqual(result, expected_datetimes) + _shared_utils.assert_array_equal(result, expected_datetimes) - @tests.skip_nc_time_axis + @_shared_utils.skip_nc_time_axis def test_360_day_calendar_attribute(self): calendar = "360_day" unit = Unit("days since 2000-02-01 00:00:00", calendar=calendar) coord = AuxCoord([0, 3, 6], "time", units=unit) result = _fixup_dates(coord, coord.points) - self.assertEqual(result[0].calendar, calendar) - - -if __name__ == "__main__": - tests.main() + assert result[0].calendar == calendar diff --git a/lib/iris/tests/unit/plot/test__get_plot_defn.py b/lib/iris/tests/unit/plot/test__get_plot_defn.py index 4032c8792d..81d54f9716 100644 --- a/lib/iris/tests/unit/plot/test__get_plot_defn.py +++ b/lib/iris/tests/unit/plot/test__get_plot_defn.py @@ -4,35 +4,28 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot._get_plot_defn` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import iris.coords +from iris.tests import _shared_utils from iris.tests.stock import simple_2d, simple_2d_w_multidim_coords -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot -class Test_get_plot_defn(tests.IrisTest): +@_shared_utils.skip_plot +class Test_get_plot_defn: def test_axis_order_xy(self): cube_xy = simple_2d() defn = iplt._get_plot_defn(cube_xy, iris.coords.POINT_MODE) - self.assertEqual([coord.name() for coord in defn.coords], ["bar", "foo"]) + assert [coord.name() for coord in defn.coords] == ["bar", "foo"] def test_axis_order_yx(self): cube_yx = simple_2d() cube_yx.transpose() defn = iplt._get_plot_defn(cube_yx, iris.coords.POINT_MODE) - self.assertEqual([coord.name() for coord in defn.coords], ["foo", "bar"]) + assert [coord.name() for coord in defn.coords] == ["foo", "bar"] def test_2d_coords(self): cube = simple_2d_w_multidim_coords() defn = iplt._get_plot_defn(cube, iris.coords.BOUND_MODE) - self.assertEqual([coord.name() for coord in defn.coords], ["bar", "foo"]) - - -if __name__ == "__main__": - tests.main() + assert [coord.name() for coord in defn.coords] == ["bar", "foo"] diff --git a/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py b/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py index 7b39043559..80f01be708 100644 --- a/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py +++ b/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py @@ -5,70 +5,64 @@ """Unit tests for the `iris.plot._get_plot_defn_custom_coords_picked` function. """ - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip +import pytest from iris.coords import BOUND_MODE, POINT_MODE +from iris.tests import _shared_utils from iris.tests.stock import hybrid_height, simple_2d, simple_2d_w_multidim_coords -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot -class Test_get_plot_defn_custom_coords_picked(tests.IrisTest): +@_shared_utils.skip_plot +class Test_get_plot_defn_custom_coords_picked: def test_1d_coords(self): cube = simple_2d() defn = iplt._get_plot_defn_custom_coords_picked( cube, ("foo", "bar"), POINT_MODE ) - self.assertEqual([coord.name() for coord in defn.coords], ["bar", "foo"]) - self.assertFalse(defn.transpose) + assert [coord.name() for coord in defn.coords] == ["bar", "foo"] + assert not defn.transpose def test_1d_coords_swapped(self): cube = simple_2d() defn = iplt._get_plot_defn_custom_coords_picked( cube, ("bar", "foo"), POINT_MODE ) - self.assertEqual([coord.name() for coord in defn.coords], ["foo", "bar"]) - self.assertTrue(defn.transpose) + assert [coord.name() for coord in defn.coords] == ["foo", "bar"] + assert defn.transpose def test_1d_coords_as_integers(self): cube = simple_2d() defn = iplt._get_plot_defn_custom_coords_picked(cube, (1, 0), POINT_MODE) - self.assertEqual([coord for coord in defn.coords], [0, 1]) - self.assertFalse(defn.transpose) + assert [coord for coord in defn.coords] == [0, 1] + assert not defn.transpose def test_1d_coords_as_integers_swapped(self): cube = simple_2d() defn = iplt._get_plot_defn_custom_coords_picked(cube, (0, 1), POINT_MODE) - self.assertEqual([coord for coord in defn.coords], [1, 0]) - self.assertTrue(defn.transpose) + assert [coord for coord in defn.coords] == [1, 0] + assert defn.transpose def test_2d_coords(self): cube = simple_2d_w_multidim_coords() defn = iplt._get_plot_defn_custom_coords_picked( cube, ("foo", "bar"), BOUND_MODE ) - self.assertEqual([coord.name() for coord in defn.coords], ["bar", "foo"]) - self.assertFalse(defn.transpose) + assert [coord.name() for coord in defn.coords] == ["bar", "foo"] + assert not defn.transpose def test_2d_coords_as_integers(self): cube = simple_2d_w_multidim_coords() defn = iplt._get_plot_defn_custom_coords_picked(cube, (0, 1), BOUND_MODE) - self.assertEqual([coord for coord in defn.coords], [1, 0]) - self.assertTrue(defn.transpose) + assert [coord for coord in defn.coords] == [1, 0] + assert defn.transpose def test_span_check(self): cube = hybrid_height() emsg = "don't span the 2 data dimensions" - with self.assertRaisesRegex(ValueError, emsg): + with pytest.raises(ValueError, match=emsg): iplt._get_plot_defn_custom_coords_picked( cube, ("sigma", "level_height"), POINT_MODE ) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test__get_plot_objects.py b/lib/iris/tests/unit/plot/test__get_plot_objects.py index fbccbe94fb..20eea759af 100644 --- a/lib/iris/tests/unit/plot/test__get_plot_objects.py +++ b/lib/iris/tests/unit/plot/test__get_plot_objects.py @@ -3,42 +3,32 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot._get_plot_objects` function.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip +import pytest import iris.cube +from iris.tests import _shared_utils -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: from iris.plot import _get_plot_objects -@tests.skip_plot -class Test__get_plot_objects(tests.IrisTest): +@_shared_utils.skip_plot +class Test__get_plot_objects: def test_scalar(self): cube1 = iris.cube.Cube(1) cube2 = iris.cube.Cube(1) expected = (cube1, cube2, 1, 1, ()) result = _get_plot_objects((cube1, cube2)) - self.assertTupleEqual(expected, result) + assert result == expected def test_mismatched_size_first_scalar(self): cube1 = iris.cube.Cube(1) cube2 = iris.cube.Cube([1, 42]) - with self.assertRaisesRegex( - ValueError, "x and y-axis objects are not compatible" - ): + with pytest.raises(ValueError, match="x and y-axis objects are not compatible"): _get_plot_objects((cube1, cube2)) def test_mismatched_size_second_scalar(self): cube1 = iris.cube.Cube(1) cube2 = iris.cube.Cube([1, 42]) - with self.assertRaisesRegex( - ValueError, "x and y-axis objects are not compatible" - ): + with pytest.raises(ValueError, match="x and y-axis objects are not compatible"): _get_plot_objects((cube2, cube1)) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test__replace_axes_with_cartopy_axes.py b/lib/iris/tests/unit/plot/test__replace_axes_with_cartopy_axes.py index cac42bb765..e8d4b6d1cd 100644 --- a/lib/iris/tests/unit/plot/test__replace_axes_with_cartopy_axes.py +++ b/lib/iris/tests/unit/plot/test__replace_axes_with_cartopy_axes.py @@ -4,20 +4,21 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.__replace_axes_with_cartopy_axes` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import cartopy.crs as ccrs import matplotlib.pyplot as plt +import pytest from iris.plot import _replace_axes_with_cartopy_axes +from iris.tests import _shared_utils -@tests.skip_plot -class Test_replace_axes_with_cartopy_axes(tests.IrisTest): - def setUp(self): +@_shared_utils.skip_plot +class Test_replace_axes_with_cartopy_axes: + @pytest.fixture(autouse=True) + def _setup(self): self.fig = plt.figure() + yield + plt.close(self.fig) def test_preserve_position(self): position = [0.17, 0.65, 0.2, 0.2] @@ -32,18 +33,11 @@ def test_preserve_position(self): # get_position returns mpl.transforms.Bbox object, for which equality does # not appear to be implemented. Compare the bounds (tuple) instead. - self.assertEqual(expected.get_position().bounds, result.get_position().bounds) + assert expected.get_position().bounds == result.get_position().bounds def test_ax_on_subfigure(self): subfig, _ = self.fig.subfigures(nrows=2) subfig.subplots() _replace_axes_with_cartopy_axes(ccrs.PlateCarree()) result = plt.gca() - self.assertIs(result.get_figure(), subfig) - - def tearDown(self): - plt.close(self.fig) - - -if __name__ == "__main__": - tests.main() + assert result.get_figure() is subfig diff --git a/lib/iris/tests/unit/plot/test_contour.py b/lib/iris/tests/unit/plot/test_contour.py index 43c0564ff4..e874c756ce 100644 --- a/lib/iris/tests/unit/plot/test_contour.py +++ b/lib/iris/tests/unit/plot/test_contour.py @@ -4,28 +4,26 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.contour` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): iplt.contour(self.cube, coords=("bar", "str_coord")) - self.assertPointsTickLabels("yaxis") + self.assert_points_tick_labels("yaxis") def test_xaxis_labels(self): iplt.contour(self.cube, coords=("str_coord", "bar")) - self.assertPointsTickLabels("xaxis") + self.assert_points_tick_labels("xaxis") def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -34,7 +32,7 @@ def test_yaxis_labels_with_axes(self): ax = fig.add_subplot(111) iplt.contour(self.cube, axes=ax, coords=("bar", "str_coord")) plt.close(fig) - self.assertPointsTickLabels("yaxis", ax) + self.assert_points_tick_labels("yaxis", ax) def test_xaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -43,20 +41,21 @@ def test_xaxis_labels_with_axes(self): ax = fig.add_subplot(111) iplt.contour(self.cube, axes=ax, coords=("str_coord", "bar")) plt.close(fig) - self.assertPointsTickLabels("xaxis", ax) + self.assert_points_tick_labels("xaxis", ax) def test_geoaxes_exception(self): import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) - self.assertRaises(TypeError, iplt.contour, self.lat_lon_cube, axes=ax) + pytest.raises(TypeError, iplt.contour, self.lat_lon_cube, axes=ax) plt.close(fig) -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=False) self.foo = self.cube.coord("foo").points @@ -65,9 +64,5 @@ def setUp(self): self.bar_index = np.arange(self.bar.size) self.data = self.cube.data self.dataT = self.data.T - self.mpl_patch = self.patch("matplotlib.pyplot.contour") + self.mpl_patch = mocker.patch("matplotlib.pyplot.contour") self.draw_func = iplt.contour - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test_contourf.py b/lib/iris/tests/unit/plot/test_contourf.py index 59fe631b67..6ee170f4c1 100644 --- a/lib/iris/tests/unit/plot/test_contourf.py +++ b/lib/iris/tests/unit/plot/test_contourf.py @@ -4,31 +4,27 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.contourf` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - -from unittest import mock - import matplotlib.pyplot as plt import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): iplt.contourf(self.cube, coords=("bar", "str_coord")) - self.assertPointsTickLabels("yaxis") + self.assert_points_tick_labels("yaxis") def test_xaxis_labels(self): iplt.contourf(self.cube, coords=("str_coord", "bar")) - self.assertPointsTickLabels("xaxis") + self.assert_points_tick_labels("xaxis") def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -37,7 +33,7 @@ def test_yaxis_labels_with_axes(self): ax = fig.add_subplot(111) iplt.contourf(self.cube, axes=ax, coords=("bar", "str_coord")) plt.close(fig) - self.assertPointsTickLabels("yaxis", ax) + self.assert_points_tick_labels("yaxis", ax) def test_xaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -46,20 +42,21 @@ def test_xaxis_labels_with_axes(self): ax = fig.add_subplot(111) iplt.contourf(self.cube, axes=ax, coords=("str_coord", "bar")) plt.close(fig) - self.assertPointsTickLabels("xaxis", ax) + self.assert_points_tick_labels("xaxis", ax) def test_geoaxes_exception(self): import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) - self.assertRaises(TypeError, iplt.contourf, self.lat_lon_cube, axes=ax) + pytest.raises(TypeError, iplt.contourf, self.lat_lon_cube, axes=ax) plt.close(fig) -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=False) self.foo = self.cube.coord("foo").points @@ -68,29 +65,31 @@ def setUp(self): self.bar_index = np.arange(self.bar.size) self.data = self.cube.data self.dataT = self.data.T - mocker = mock.Mock(wraps=plt.contourf) - self.mpl_patch = self.patch("matplotlib.pyplot.contourf", mocker) + self.mpl_patch = mocker.patch("matplotlib.pyplot.contourf") self.draw_func = iplt.contourf -@tests.skip_plot -class TestAntialias(tests.IrisTest): - def setUp(self): +@_shared_utils.skip_plot +class TestAntialias: + @pytest.fixture(autouse=True) + def _setup(self): self.fig = plt.figure() + yield + plt.close(self.fig) - def test_skip_contour(self): + def test_skip_contour(self, mocker): # Contours should not be added if data is all below second level. See #4086. cube = simple_2d() levels = [5, 15, 20, 200] colors = ["b", "r", "y"] - with mock.patch("matplotlib.pyplot.contour") as mocked_contour: - iplt.contourf(cube, levels=levels, colors=colors, antialiased=True) + mocked_contour = mocker.patch("matplotlib.pyplot.contour") + iplt.contourf(cube, levels=levels, colors=colors, antialiased=True) mocked_contour.assert_not_called() - def test_apply_contour_nans(self): + def test_apply_contour_nans(self, mocker): # Presence of nans should not prevent contours being added. cube = simple_2d() cube.data = cube.data.astype(np.float64) @@ -99,14 +98,7 @@ def test_apply_contour_nans(self): levels = [2, 4, 6, 8] colors = ["b", "r", "y"] - with mock.patch("matplotlib.pyplot.contour") as mocked_contour: - iplt.contourf(cube, levels=levels, colors=colors, antialiased=True) + mocked_contour = mocker.patch("matplotlib.pyplot.contour") + iplt.contourf(cube, levels=levels, colors=colors, antialiased=True) mocked_contour.assert_called_once() - - def tearDown(self): - plt.close(self.fig) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test_hist.py b/lib/iris/tests/unit/plot/test_hist.py index feef8f1062..c4651e846e 100644 --- a/lib/iris/tests/unit/plot/test_hist.py +++ b/lib/iris/tests/unit/plot/test_hist.py @@ -3,47 +3,43 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.hist` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - -from unittest import mock import numpy as np import pytest from iris.coords import AncillaryVariable, AuxCoord, CellMeasure, DimCoord from iris.cube import Cube +from iris.tests import _shared_utils -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot +@_shared_utils.skip_plot class Test: @pytest.fixture(autouse=True) - def create_data(self): + def _create_data(self): self.data = np.array([0, 100, 110, 120, 200, 320]) @pytest.mark.parametrize( "x", [AuxCoord, Cube, DimCoord, CellMeasure, AncillaryVariable] ) - def test_simple(self, x): - with mock.patch("matplotlib.pyplot.hist") as mocker: - iplt.hist(x(self.data)) + def test_simple(self, x, mocker): + mock_patch = mocker.patch("matplotlib.pyplot.hist") + iplt.hist(x(self.data)) # mocker.assert_called_once_with is not working as expected with - # _DimensionalMetadata objects so we use np.testing array equality + # _DimensionalMetadata objects so we use array equality # checks instead. - args, kwargs = mocker.call_args + args, kwargs = mock_patch.call_args assert len(args) == 1 - np.testing.assert_array_equal(args[0], self.data) + _shared_utils.assert_array_equal(args[0], self.data) - def test_kwargs(self): + def test_kwargs(self, mocker): cube = Cube(self.data) bins = [0, 150, 250, 350] - with mock.patch("matplotlib.pyplot.hist") as mocker: - iplt.hist(cube, bins=bins) - mocker.assert_called_once_with(self.data, bins=bins) + mock_patch = mocker.patch("matplotlib.pyplot.hist") + iplt.hist(cube, bins=bins) + mock_patch.assert_called_once_with(self.data, bins=bins) def test_unsupported_input(self): with pytest.raises(TypeError, match="x must be a"): diff --git a/lib/iris/tests/unit/plot/test_outline.py b/lib/iris/tests/unit/plot/test_outline.py index dc1b27487b..615febfed2 100644 --- a/lib/iris/tests/unit/plot/test_outline.py +++ b/lib/iris/tests/unit/plot/test_outline.py @@ -3,29 +3,26 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.outline` function.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): iplt.outline(self.cube, coords=("bar", "str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): iplt.outline(self.cube, coords=("str_coord", "bar")) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") def test_xaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -35,7 +32,7 @@ def test_xaxis_labels_with_axes(self): ax.set_xlim(0, 3) iplt.outline(self.cube, coords=("str_coord", "bar"), axes=ax) plt.close(fig) - self.assertPointsTickLabels("xaxis", ax) + self.assert_points_tick_labels("xaxis", ax) def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -45,20 +42,21 @@ def test_yaxis_labels_with_axes(self): ax.set_ylim(0, 3) iplt.outline(self.cube, axes=ax, coords=("bar", "str_coord")) plt.close(fig) - self.assertPointsTickLabels("yaxis", ax) + self.assert_points_tick_labels("yaxis", ax) def test_geoaxes_exception(self): import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) - self.assertRaises(TypeError, iplt.outline, self.lat_lon_cube, axes=ax) + pytest.raises(TypeError, iplt.outline, self.lat_lon_cube, axes=ax) plt.close(fig) -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=True) coord = self.cube.coord("foo") @@ -69,9 +67,5 @@ def setUp(self): self.bar_index = np.arange(coord.points.size + 1) self.data = self.cube.data self.dataT = self.data.T - self.mpl_patch = self.patch("matplotlib.pyplot.pcolormesh") + self.mpl_patch = mocker.patch("matplotlib.pyplot.pcolormesh") self.draw_func = iplt.outline - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test_pcolor.py b/lib/iris/tests/unit/plot/test_pcolor.py index 219df4d446..27f6a7b6ed 100644 --- a/lib/iris/tests/unit/plot/test_pcolor.py +++ b/lib/iris/tests/unit/plot/test_pcolor.py @@ -4,10 +4,7 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.pcolor` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - +from iris.tests import _shared_utils from iris.tests.unit.plot import TestGraphicStringCoord from iris.tests.unit.plot._blockplot_common import ( Mixin2dCoordsContigTol, @@ -15,35 +12,28 @@ MixinStringCoordPlot, ) -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt PLOT_FUNCTION_TO_TEST = iplt.pcolor -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord): def blockplot_func(self): return PLOT_FUNCTION_TO_TEST -@tests.skip_plot -class Test2dCoords(tests.IrisTest, Mixin2dCoordsPlot): - def setUp(self): - self.blockplot_setup() - +@_shared_utils.skip_plot +class Test2dCoords(Mixin2dCoordsPlot): def blockplot_func(self): return PLOT_FUNCTION_TO_TEST -@tests.skip_plot -class Test2dContigTol(tests.IrisTest, Mixin2dCoordsContigTol): +@_shared_utils.skip_plot +class Test2dContigTol(Mixin2dCoordsContigTol): # Extra call kwargs expected. additional_kwargs = dict(antialiased=True, snap=False) def blockplot_func(self): return PLOT_FUNCTION_TO_TEST - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test_pcolormesh.py b/lib/iris/tests/unit/plot/test_pcolormesh.py index a5525770f2..11c54b06cb 100644 --- a/lib/iris/tests/unit/plot/test_pcolormesh.py +++ b/lib/iris/tests/unit/plot/test_pcolormesh.py @@ -3,11 +3,7 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.pcolormesh` function.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - +from iris.tests import _shared_utils from iris.tests.unit.plot import TestGraphicStringCoord from iris.tests.unit.plot._blockplot_common import ( Mixin2dCoordsContigTol, @@ -15,35 +11,28 @@ MixinStringCoordPlot, ) -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt PLOT_FUNCTION_TO_TEST = iplt.pcolormesh -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord): def blockplot_func(self): return PLOT_FUNCTION_TO_TEST -@tests.skip_plot -class Test2dCoords(tests.IrisTest, Mixin2dCoordsPlot): - def setUp(self): - self.blockplot_setup() - +@_shared_utils.skip_plot +class Test2dCoords(Mixin2dCoordsPlot): def blockplot_func(self): return PLOT_FUNCTION_TO_TEST -@tests.skip_plot -class Test2dContigTol(tests.IrisTest, Mixin2dCoordsContigTol): +@_shared_utils.skip_plot +class Test2dContigTol(Mixin2dCoordsContigTol): # Extra call kwargs expected -- unlike 'pcolor', there are none. additional_kwargs = {} def blockplot_func(self): return PLOT_FUNCTION_TO_TEST - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test_plot.py b/lib/iris/tests/unit/plot/test_plot.py index 6adf1c4cf5..76225557f0 100644 --- a/lib/iris/tests/unit/plot/test_plot.py +++ b/lib/iris/tests/unit/plot/test_plot.py @@ -4,17 +4,15 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.plot` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest import iris.coord_systems as ics import iris.coords as coords +from iris.tests import _shared_utils from iris.tests.unit.plot import TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import cartopy.crs as ccrs import cartopy.mpl.geoaxes from matplotlib.path import Path @@ -23,20 +21,22 @@ import iris.plot as iplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): - def setUp(self): - super().setUp() + parent_setup = TestGraphicStringCoord._setup + + @pytest.fixture(autouse=True) + def _setup(self, parent_setup): self.cube = self.cube[0, :] self.lat_lon_cube = self.lat_lon_cube[0, :] def test_yaxis_labels(self): iplt.plot(self.cube, self.cube.coord("str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): iplt.plot(self.cube.coord("str_coord"), self.cube) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -45,7 +45,7 @@ def test_yaxis_labels_with_axes(self): ax = fig.add_subplot(111) iplt.plot(self.cube, self.cube.coord("str_coord"), axes=ax) plt.close(fig) - self.assertBoundsTickLabels("yaxis", ax) + self.assert_bounds_tick_labels("yaxis", ax) def test_xaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -54,7 +54,7 @@ def test_xaxis_labels_with_axes(self): ax = fig.add_subplot(111) iplt.plot(self.cube.coord("str_coord"), self.cube, axes=ax) plt.close(fig) - self.assertBoundsTickLabels("xaxis", ax) + self.assert_bounds_tick_labels("xaxis", ax) def test_plot_longitude(self): import matplotlib.pyplot as plt @@ -65,14 +65,15 @@ def test_plot_longitude(self): plt.close(fig) -@tests.skip_plot -class TestTrajectoryWrap(tests.IrisTest): +@_shared_utils.skip_plot +class TestTrajectoryWrap: """Test that a line plot of geographic coordinates wraps around the end of the coordinates rather than plotting across the map. """ - def setUp(self): + @pytest.fixture(autouse=True) + def _setup(self): plt.figure() self.geog_cs = ics.GeogCS(6371229.0) self.plate_carree = self.geog_cs.as_cartopy_projection() @@ -85,7 +86,7 @@ def lon_lat_coords(self, lons, lats, cs=None): coords.AuxCoord(lats, "latitude", units="degrees", coord_system=cs), ) - def assertPathsEqual(self, expected, actual): + def assert_paths_equal(self, expected, actual): """Assert that the given paths are equal once STOP vertices have been removed. @@ -95,17 +96,15 @@ def assertPathsEqual(self, expected, actual): # Remove Path.STOP vertices everts = expected.vertices[np.where(expected.codes != Path.STOP)] averts = actual.vertices[np.where(actual.codes != Path.STOP)] - self.assertArrayAlmostEqual(everts, averts) - self.assertArrayEqual(expected.codes, actual.codes) + _shared_utils.assert_array_almost_equal(everts, averts) + _shared_utils.assert_array_equal(expected.codes, actual.codes) def check_paths(self, expected_path, expected_path_crs, lines, axes): """Check that the paths in `lines` match the given expected paths when plotted on the given geoaxes. """ - self.assertEqual( - 1, len(lines), "Expected a single line, got {}".format(len(lines)) - ) + assert 1 == len(lines), "Expected a single line, got {}".format(len(lines)) (line,) = lines inter_proj_transform = cartopy.mpl.geoaxes.InterProjectionTransform( expected_path_crs, axes.projection @@ -115,7 +114,7 @@ def check_paths(self, expected_path, expected_path_crs, lines, axes): expected = ax_transform.transform_path(expected_path) actual = line.get_transform().transform_path(line.get_path()) - self.assertPathsEqual(expected, actual) + self.assert_paths_equal(expected, actual) def test_simple(self): lon, lat = self.lon_lat_coords([359, 1], [0, 0]) @@ -255,7 +254,3 @@ def test_rotated(self): grid_north_pole_longitude=120, north_pole_grid_longitude=45, ) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test_points.py b/lib/iris/tests/unit/plot/test_points.py index 0d713e3d84..41babd53d6 100644 --- a/lib/iris/tests/unit/plot/test_points.py +++ b/lib/iris/tests/unit/plot/test_points.py @@ -3,29 +3,26 @@ # This file is part of Iris and is released under the BSD license. # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.points` function.""" - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): iplt.points(self.cube, coords=("bar", "str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): iplt.points(self.cube, coords=("str_coord", "bar")) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") def test_xaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -35,7 +32,7 @@ def test_xaxis_labels_with_axes(self): ax.set_xlim(0, 3) iplt.points(self.cube, coords=("str_coord", "bar"), axes=ax) plt.close(fig) - self.assertPointsTickLabels("xaxis", ax) + self.assert_points_tick_labels("xaxis", ax) def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -45,20 +42,21 @@ def test_yaxis_labels_with_axes(self): ax.set_ylim(0, 3) iplt.points(self.cube, coords=("bar", "str_coord"), axes=ax) plt.close(fig) - self.assertPointsTickLabels("yaxis", ax) + self.assert_points_tick_labels("yaxis", ax) def test_geoaxes_exception(self): import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) - self.assertRaises(TypeError, iplt.points, self.lat_lon_cube, axes=ax) + pytest.raises(TypeError, iplt.points, self.lat_lon_cube, axes=ax) plt.close(fig) -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=False) self.foo = self.cube.coord("foo").points @@ -67,9 +65,5 @@ def setUp(self): self.bar_index = np.arange(self.bar.size) self.data = None self.dataT = None - self.mpl_patch = self.patch("matplotlib.pyplot.scatter") + self.mpl_patch = mocker.patch("matplotlib.pyplot.scatter") self.draw_func = iplt.points - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/plot/test_scatter.py b/lib/iris/tests/unit/plot/test_scatter.py index 21412010ab..9a0a7db96c 100644 --- a/lib/iris/tests/unit/plot/test_scatter.py +++ b/lib/iris/tests/unit/plot/test_scatter.py @@ -4,29 +4,31 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.plot.scatter` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip +import pytest + +from iris.tests import _shared_utils from iris.tests.unit.plot import TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.plot as iplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): - def setUp(self): - super().setUp() + parent_setup = TestGraphicStringCoord._setup + + @pytest.fixture(autouse=True) + def _setup(self, parent_setup): self.cube = self.cube[0, :] self.lat_lon_cube = self.lat_lon_cube[0, :] def test_xaxis_labels(self): iplt.scatter(self.cube.coord("str_coord"), self.cube) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") def test_yaxis_labels(self): iplt.scatter(self.cube, self.cube.coord("str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -36,7 +38,7 @@ def test_xaxis_labels_with_axes(self): ax.set_xlim(0, 3) iplt.scatter(self.cube.coord("str_coord"), self.cube, axes=ax) plt.close(fig) - self.assertPointsTickLabels("xaxis", ax) + self.assert_points_tick_labels("xaxis", ax) def test_yaxis_labels_with_axes(self): import matplotlib.pyplot as plt @@ -46,7 +48,7 @@ def test_yaxis_labels_with_axes(self): ax.set_ylim(0, 3) iplt.scatter(self.cube, self.cube.coord("str_coord"), axes=ax) plt.close(fig) - self.assertPointsTickLabels("yaxis", ax) + self.assert_points_tick_labels("yaxis", ax) def test_scatter_longitude(self): import matplotlib.pyplot as plt @@ -55,7 +57,3 @@ def test_scatter_longitude(self): ax = fig.add_subplot(111) iplt.scatter(self.lat_lon_cube, self.lat_lon_cube.coord("longitude"), axes=ax) plt.close(fig) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_contour.py b/lib/iris/tests/unit/quickplot/test_contour.py index 2f3bb1a45d..8d5fe7a01c 100644 --- a/lib/iris/tests/unit/quickplot/test_contour.py +++ b/lib/iris/tests/unit/quickplot/test_contour.py @@ -4,33 +4,32 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.contour` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): qplt.contour(self.cube, coords=("bar", "str_coord")) - self.assertPointsTickLabels("yaxis") + self.assert_points_tick_labels("yaxis") def test_xaxis_labels(self): qplt.contour(self.cube, coords=("str_coord", "bar")) - self.assertPointsTickLabels("xaxis") + self.assert_points_tick_labels("xaxis") -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=False) self.foo = self.cube.coord("foo").points @@ -39,9 +38,5 @@ def setUp(self): self.bar_index = np.arange(self.bar.size) self.data = self.cube.data self.dataT = self.data.T - self.mpl_patch = self.patch("matplotlib.pyplot.contour") + self.mpl_patch = mocker.patch("matplotlib.pyplot.contour") self.draw_func = qplt.contour - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_contourf.py b/lib/iris/tests/unit/quickplot/test_contourf.py index 55c9940821..91deb3b79e 100644 --- a/lib/iris/tests/unit/quickplot/test_contourf.py +++ b/lib/iris/tests/unit/quickplot/test_contourf.py @@ -4,36 +4,32 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.contourf` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - -from unittest import mock - -import matplotlib.pyplot as plt import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): qplt.contourf(self.cube, coords=("bar", "str_coord")) - self.assertPointsTickLabels("yaxis") + self.assert_points_tick_labels("yaxis") def test_xaxis_labels(self): qplt.contourf(self.cube, coords=("str_coord", "bar")) - self.assertPointsTickLabels("xaxis") + self.assert_points_tick_labels("xaxis") -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=False) self.foo = self.cube.coord("foo").points @@ -42,12 +38,7 @@ def setUp(self): self.bar_index = np.arange(self.bar.size) self.data = self.cube.data self.dataT = self.data.T - mocker = mock.Mock(wraps=plt.contourf) - self.mpl_patch = self.patch("matplotlib.pyplot.contourf", mocker) + self.mpl_patch = mocker.patch("matplotlib.pyplot.contourf") # Also need to mock the colorbar. - self.patch("matplotlib.pyplot.colorbar") + mocker.patch("matplotlib.pyplot.colorbar") self.draw_func = qplt.contourf - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_outline.py b/lib/iris/tests/unit/quickplot/test_outline.py index 4dd924b749..1d83561f9d 100644 --- a/lib/iris/tests/unit/quickplot/test_outline.py +++ b/lib/iris/tests/unit/quickplot/test_outline.py @@ -4,33 +4,32 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.outline` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): qplt.outline(self.cube, coords=("bar", "str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): qplt.outline(self.cube, coords=("str_coord", "bar")) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=True) coord = self.cube.coord("foo") @@ -41,9 +40,5 @@ def setUp(self): self.bar_index = np.arange(coord.points.size + 1) self.data = self.cube.data self.dataT = self.data.T - self.mpl_patch = self.patch("matplotlib.pyplot.pcolormesh") + self.mpl_patch = mocker.patch("matplotlib.pyplot.pcolormesh") self.draw_func = qplt.outline - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_pcolor.py b/lib/iris/tests/unit/quickplot/test_pcolor.py index fc2ce83f0b..87d9b73530 100644 --- a/lib/iris/tests/unit/quickplot/test_pcolor.py +++ b/lib/iris/tests/unit/quickplot/test_pcolor.py @@ -4,33 +4,32 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.pcolor` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): qplt.pcolor(self.cube, coords=("bar", "str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): qplt.pcolor(self.cube, coords=("str_coord", "bar")) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=True) coord = self.cube.coord("foo") @@ -41,9 +40,5 @@ def setUp(self): self.bar_index = np.arange(coord.points.size + 1) self.data = self.cube.data self.dataT = self.data.T - self.mpl_patch = self.patch("matplotlib.pyplot.pcolor", return_value=None) + self.mpl_patch = mocker.patch("matplotlib.pyplot.pcolor", return_value=None) self.draw_func = qplt.pcolor - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_pcolormesh.py b/lib/iris/tests/unit/quickplot/test_pcolormesh.py index 6ce9d07406..b9476c0c16 100644 --- a/lib/iris/tests/unit/quickplot/test_pcolormesh.py +++ b/lib/iris/tests/unit/quickplot/test_pcolormesh.py @@ -4,33 +4,32 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.pcolormesh` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): qplt.pcolormesh(self.cube, coords=("bar", "str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): qplt.pcolormesh(self.cube, coords=("str_coord", "bar")) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=True) coord = self.cube.coord("foo") @@ -41,9 +40,5 @@ def setUp(self): self.bar_index = np.arange(coord.points.size + 1) self.data = self.cube.data self.dataT = self.data.T - self.mpl_patch = self.patch("matplotlib.pyplot.pcolormesh", return_value=None) + self.mpl_patch = mocker.patch("matplotlib.pyplot.pcolormesh", return_value=None) self.draw_func = qplt.pcolormesh - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_plot.py b/lib/iris/tests/unit/quickplot/test_plot.py index 35e1eae470..6f4c71a4f1 100644 --- a/lib/iris/tests/unit/quickplot/test_plot.py +++ b/lib/iris/tests/unit/quickplot/test_plot.py @@ -4,40 +4,42 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.plot` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip +import pytest + +from iris.tests import _shared_utils from iris.tests.stock import simple_1d from iris.tests.unit.plot import TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): - def setUp(self): - super().setUp() + parent_setup = TestGraphicStringCoord._setup + + @pytest.fixture(autouse=True) + def _setup(self, parent_setup): self.cube = self.cube[0, :] def test_yaxis_labels(self): qplt.plot(self.cube, self.cube.coord("str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): qplt.plot(self.cube.coord("str_coord"), self.cube) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") -class TestAxisLabels(tests.GraphicsTest): +class TestAxisLabels(_shared_utils.GraphicsTest): def test_xy_cube(self): c = simple_1d() qplt.plot(c) ax = qplt.plt.gca() x = ax.xaxis.get_label().get_text() - self.assertEqual(x, "Foo") + assert x == "Foo" y = ax.yaxis.get_label().get_text() - self.assertEqual(y, "Thingness") + assert y == "Thingness" def test_yx_cube(self): c = simple_1d() @@ -48,10 +50,6 @@ def test_yx_cube(self): qplt.plot(c) ax = qplt.plt.gca() x = ax.xaxis.get_label().get_text() - self.assertEqual(x, "Thingness") + assert x == "Thingness" y = ax.yaxis.get_label().get_text() - self.assertEqual(y, "Foo") - - -if __name__ == "__main__": - tests.main() + assert y == "Foo" diff --git a/lib/iris/tests/unit/quickplot/test_points.py b/lib/iris/tests/unit/quickplot/test_points.py index b28c37bf87..d55b3daadf 100644 --- a/lib/iris/tests/unit/quickplot/test_points.py +++ b/lib/iris/tests/unit/quickplot/test_points.py @@ -4,33 +4,32 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.points` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip - import numpy as np +import pytest +from iris.tests import _shared_utils from iris.tests.stock import simple_2d from iris.tests.unit.plot import MixinCoords, TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): def test_yaxis_labels(self): qplt.points(self.cube, coords=("bar", "str_coord")) - self.assertBoundsTickLabels("yaxis") + self.assert_bounds_tick_labels("yaxis") def test_xaxis_labels(self): qplt.points(self.cube, coords=("str_coord", "bar")) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") -@tests.skip_plot -class TestCoords(tests.IrisTest, MixinCoords): - def setUp(self): +@_shared_utils.skip_plot +class TestCoords(MixinCoords): + @pytest.fixture(autouse=True) + def _setup(self, mocker): # We have a 2d cube with dimensionality (bar: 3; foo: 4) self.cube = simple_2d(with_bounds=False) self.foo = self.cube.coord("foo").points @@ -39,9 +38,5 @@ def setUp(self): self.bar_index = np.arange(self.bar.size) self.data = None self.dataT = None - self.mpl_patch = self.patch("matplotlib.pyplot.scatter") + self.mpl_patch = mocker.patch("matplotlib.pyplot.scatter") self.draw_func = qplt.points - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/quickplot/test_scatter.py b/lib/iris/tests/unit/quickplot/test_scatter.py index db3e9948a0..e6c7177860 100644 --- a/lib/iris/tests/unit/quickplot/test_scatter.py +++ b/lib/iris/tests/unit/quickplot/test_scatter.py @@ -4,29 +4,27 @@ # See LICENSE in the root of the repository for full licensing details. """Unit tests for the `iris.quickplot.scatter` function.""" -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests # isort:skip +import pytest + +from iris.tests import _shared_utils from iris.tests.unit.plot import TestGraphicStringCoord -if tests.MPL_AVAILABLE: +if _shared_utils.MPL_AVAILABLE: import iris.quickplot as qplt -@tests.skip_plot +@_shared_utils.skip_plot class TestStringCoordPlot(TestGraphicStringCoord): - def setUp(self): - super().setUp() + parent_setup = TestGraphicStringCoord._setup + + @pytest.fixture(autouse=True) + def _setup(self, parent_setup): self.cube = self.cube[0, :] def test_xaxis_labels(self): qplt.scatter(self.cube.coord("str_coord"), self.cube) - self.assertBoundsTickLabels("xaxis") + self.assert_bounds_tick_labels("xaxis") def test_yaxis_labels(self): qplt.scatter(self.cube, self.cube.coord("str_coord")) - self.assertBoundsTickLabels("yaxis") - - -if __name__ == "__main__": - tests.main() + self.assert_bounds_tick_labels("yaxis")