Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/iris/tests/_shared_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@

#: Basepath for test results.
_RESULT_PATH = os.path.join(os.path.dirname(__file__), "results")
MIN_PICKLE_PROTOCOL = 4


def _assert_masked_array(assertion, a, b, strict, **kwargs):
Expand Down
13 changes: 6 additions & 7 deletions lib/iris/tests/integration/test_Datums.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for :class:`iris.coord_systems` datum support."""

# 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 numpy as np
import pytest

from iris.coord_systems import GeogCS, LambertConformal
from iris.tests import _shared_utils


class TestDatumTransformation(tests.IrisTest):
def setUp(self):
class TestDatumTransformation:
@pytest.fixture(autouse=True)
def _setup(self):
self.x_points = np.array([-1.5])
self.y_points = np.array([50.5])

Expand Down Expand Up @@ -48,4 +47,4 @@ def test_transform_points_datum(self):
self.start_crs, self.x_points, self.y_points
)

self.assertArrayEqual(expected, actual)
_shared_utils.assert_array_equal(expected, actual)
17 changes: 5 additions & 12 deletions lib/iris/tests/integration/test_PartialDateTime.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,20 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for :class:`iris.time.PartialDateTime`."""

# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests # isort:skip

import iris
from iris.tests import _shared_utils
from iris.time import PartialDateTime


class Test(tests.IrisTest):
@tests.skip_data
class Test:
@_shared_utils.skip_data
def test_cftime_interface(self):
# The `netcdf4` Python module introduced new calendar classes by v1.2.7
# This test is primarily of this interface, so the
# final test assertion is simple.
filename = tests.get_data_path(("PP", "structured", "small.pp"))
filename = _shared_utils.get_data_path(("PP", "structured", "small.pp"))
cube = iris.load_cube(filename)
pdt = PartialDateTime(year=1992, month=10, day=1, hour=2)
time_constraint = iris.Constraint(time=lambda cell: cell < pdt)
sub_cube = cube.extract(time_constraint)
self.assertEqual(sub_cube.coord("time").points.shape, (1,))


if __name__ == "__main__":
tests.main()
assert sub_cube.coord("time").points.shape == (1,)
46 changes: 17 additions & 29 deletions lib/iris/tests/integration/test_climatology.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,20 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for loading and saving netcdf files."""

# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests # isort:skip

from os.path import dirname
from os.path import join as path_join
from os.path import sep as os_sep
import shutil
import tempfile

import pytest

import iris
from iris.tests import stock
from iris.tests import _shared_utils, stock
from iris.tests.stock.netcdf import ncgen_from_cdl


class TestClimatology(tests.IrisTest):
class TestClimatology:
reference_cdl_path = os_sep.join(
[
dirname(tests.__file__),
dirname(iris.tests.__file__),
(
"results/integration/climatology/TestClimatology/"
"reference_simpledata.cdl"
Expand Down Expand Up @@ -51,29 +46,25 @@ def _load_sanitised_cube(filepath):
cube.var_name = None
return cube

@classmethod
def setUpClass(cls):
@pytest.fixture(autouse=True, scope="class")
def _setup(self, request, tmp_path_factory):
# Create a temp directory for temp files.
cls.temp_dir = tempfile.mkdtemp()
cls.path_ref_cdl = path_join(cls.temp_dir, "standard.cdl")
cls.path_ref_nc = path_join(cls.temp_dir, "standard.nc")
cls = request.cls
cls.temp_dir = tmp_path_factory.mktemp("temp")
cls.path_ref_cdl = cls.temp_dir / "standard.cdl"
cls.path_ref_nc = cls.temp_dir / "standard.nc"
# Create reference CDL and netcdf files (with ncgen).
ncgen_from_cdl(
cdl_str=cls._simple_cdl_string(),
cdl_path=cls.path_ref_cdl,
nc_path=cls.path_ref_nc,
)

cls.path_temp_nc = path_join(cls.temp_dir, "tmp.nc")
cls.path_temp_nc = cls.temp_dir / "tmp.nc"

# Create reference cube.
cls.cube_ref = stock.climatology_3d()

@classmethod
def tearDownClass(cls):
# Destroy a temp directory for temp files.
shutil.rmtree(cls.temp_dir)

###############################################################################
# Round-trip tests

Expand All @@ -82,14 +73,15 @@ def test_cube_to_cube(self):
# reference cube.
iris.save(self.cube_ref, self.path_temp_nc)
cube = self._load_sanitised_cube(self.path_temp_nc)
self.assertEqual(cube, self.cube_ref)
assert cube == self.cube_ref

def test_file_to_file(self):
def test_file_to_file(self, request):
# Load cube from reference file, save same cube to file, test against
# reference CDL.
cube = iris.load_cube(self.path_ref_nc)
iris.save(cube, self.path_temp_nc)
self.assertCDL(
_shared_utils.assert_CDL(
request,
self.path_temp_nc,
reference_filename=self.reference_cdl_path,
flags="",
Expand All @@ -105,8 +97,4 @@ def test_file_to_file(self):
def test_load_from_file(self):
# Create cube from file, test against reference cube.
cube = self._load_sanitised_cube(self.path_ref_nc)
self.assertEqual(cube, self.cube_ref)


if __name__ == "__main__":
tests.main()
assert cube == self.cube_ref
36 changes: 13 additions & 23 deletions lib/iris/tests/integration/test_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,24 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for :class:`iris.cube.Cube`."""

# 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 iris
from iris._lazy_data import as_lazy_data, is_lazy_data
from iris.analysis import MEAN
from iris.cube import Cube
from iris.tests import _shared_utils


class Test_aggregated_by(tests.IrisTest):
@tests.skip_data
def test_agg_by_aux_coord(self):
problem_test_file = tests.get_data_path(
class Test_aggregated_by:
@_shared_utils.skip_data
def test_agg_by_aux_coord(self, mocker):
problem_test_file = _shared_utils.get_data_path(
("NetCDF", "testing", "small_theta_colpex.nc")
)
# While loading, "turn off" loading small variables as real data.
with mock.patch("iris.fileformats.netcdf.loader._LAZYVAR_MIN_BYTES", 0):
cube = iris.load_cube(problem_test_file, "air_potential_temperature")

mocker.patch("iris.fileformats.netcdf.loader._LAZYVAR_MIN_BYTES", 0)
cube = iris.load_cube(problem_test_file, "air_potential_temperature")
# Test aggregating by aux coord, notably the `forecast_period` aux
# coord on `cube`, whose `_points` attribute is a lazy array.
# This test then ensures that aggregating using `points` instead is
Expand All @@ -38,29 +32,25 @@ def test_agg_by_aux_coord(self):
# triggered the load of the coordinate's data.
forecast_period_coord = cube.coord("forecast_period")

self.assertTrue(is_lazy_data(forecast_period_coord.core_points()))
assert is_lazy_data(forecast_period_coord.core_points())

# Now confirm we can aggregate along this coord.
res_cube = cube.aggregated_by("forecast_period", MEAN)
res_cell_methods = res_cube.cell_methods[0]
self.assertEqual(res_cell_methods.coord_names, ("forecast_period",))
self.assertEqual(res_cell_methods.method, "mean")
assert res_cell_methods.coord_names == ("forecast_period",)
assert res_cell_methods.method == "mean"


class TestDataFillValue(tests.IrisTest):
class TestDataFillValue:
def test_real(self):
data = np.ma.masked_array([1, 2, 3], [0, 1, 0], fill_value=10)
cube = Cube(data)
cube.data.fill_value = 20
self.assertEqual(cube.data.fill_value, 20)
assert cube.data.fill_value == 20

def test_lazy(self):
data = np.ma.masked_array([1, 2, 3], [0, 1, 0], fill_value=10)
data = as_lazy_data(data)
cube = Cube(data)
cube.data.fill_value = 20
self.assertEqual(cube.data.fill_value, 20)


if __name__ == "__main__":
tests.main()
assert cube.data.fill_value == 20
68 changes: 28 additions & 40 deletions lib/iris/tests/integration/test_ff.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,35 @@
# See LICENSE in the root of the repository for full licensing details.
"""Integration tests for loading LBC fieldsfiles."""

# 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

import iris
from iris.tests import _shared_utils


@tests.skip_data
class TestLBC(tests.IrisTest):
def setUp(self):
@_shared_utils.skip_data
class TestLBC:
@pytest.fixture(autouse=True)
def _setup(self):
# Load multiple cubes from a test file.
file_path = tests.get_data_path(("FF", "lbc", "small_lbc"))
file_path = _shared_utils.get_data_path(("FF", "lbc", "small_lbc"))
self.all_cubes = iris.load(file_path)
# Select the second cube for detailed checks (the first is orography).
self.test_cube = self.all_cubes[1]

def test_various_cubes_shapes(self):
# Check a few aspects of the loaded cubes.
cubes = self.all_cubes
self.assertEqual(len(cubes), 10)
self.assertEqual(cubes[0].shape, (16, 16))
self.assertEqual(cubes[1].shape, (2, 4, 16, 16))
self.assertEqual(cubes[3].shape, (2, 5, 16, 16))
assert len(cubes) == 10
assert cubes[0].shape == (16, 16)
assert cubes[1].shape == (2, 4, 16, 16)
assert cubes[3].shape == (2, 5, 16, 16)

def test_cube_coords(self):
# Check coordinates of one cube.
cube = self.test_cube
self.assertEqual(len(cube.coords()), 8)
assert len(cube.coords()) == 8
for name, shape in [
("forecast_reference_time", (1,)),
("time", (2,)),
Expand All @@ -47,24 +44,20 @@ def test_cube_coords(self):
("grid_longitude", (16,)),
]:
coords = cube.coords(name)
self.assertEqual(
len(coords),
1,
"expected one {!r} coord, found {}".format(name, len(coords)),
assert len(coords) == 1, "expected one {!r} coord, found {}".format(
name, len(coords)
)
(coord,) = coords
self.assertEqual(
coord.shape,
shape,
assert coord.shape == shape, (
"coord {!r} shape is {} instead of {!r}.".format(
name, coord.shape, shape
),
)
)

def test_cube_data(self):
# Check just a few points of the data.
cube = self.test_cube
self.assertArrayAllClose(
_shared_utils.assert_array_all_close(
cube.data[:, ::2, 6, 13],
np.array([[4.218922, 10.074577], [4.626897, 6.520156]]),
atol=1.0e-6,
Expand All @@ -75,22 +68,17 @@ def test_cube_mask(self):
cube = self.test_cube
mask = np.zeros((2, 4, 16, 16), dtype=bool)
mask[:, :, 7:9, 5:11] = True
self.assertArrayEqual(cube.data.mask, mask)
_shared_utils.assert_array_equal(cube.data.mask, mask)


@tests.skip_data
class TestSkipField(tests.IrisTest):
def test_missing_lbrel(self):
infile = tests.get_data_path(("FF", "lbrel_missing"))
with mock.patch("warnings.warn") as warn_fn:
fields = iris.load(infile)
self.assertIn(
"Input field skipped as PPField creation failed : "
"error = 'Unsupported header release number: -32768'",
warn_fn.call_args[0][0],
@_shared_utils.skip_data
class TestSkipField:
def test_missing_lbrel(self, mocker):
warn_msg = (
"Input field skipped as PPField creation failed : .*"
"error = 'Unsupported header release number: -32768'"
)
self.assertEqual(len(fields), 2)


if __name__ == "__main__":
tests.main()
infile = _shared_utils.get_data_path(("FF", "lbrel_missing"))
with pytest.warns(match=warn_msg):
fields = iris.load(infile)
assert len(fields) == 2
Loading
Loading