Skip to content

Commit

Permalink
Convert to pytest, move test_rules into /rules.
Browse files Browse the repository at this point in the history
  • Loading branch information
pp-mo committed Mar 20, 2024
1 parent 0c36ec8 commit 73926d2
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 93 deletions.
48 changes: 18 additions & 30 deletions lib/iris/tests/unit/fileformats/rules/test_Loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,29 @@
# 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 :class:`iris.fileformats.rules.Loader`."""

# 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

from iris.fileformats.rules import Loader
from iris.tests._shared_utils import assert_no_warnings_regexp


class Test___init__(tests.IrisTest):
def test_normal(self):
with mock.patch("warnings.warn") as warn:
class Test___init__:
def test_normal(self, mocker):
with assert_no_warnings_regexp():
loader = Loader(
mock.sentinel.GEN_FUNC,
mock.sentinel.GEN_FUNC_KWARGS,
mock.sentinel.CONVERTER,
mocker.sentinel.GEN_FUNC,
mocker.sentinel.GEN_FUNC_KWARGS,
mocker.sentinel.CONVERTER,
)
self.assertEqual(warn.call_count, 0)
self.assertIs(loader.field_generator, mock.sentinel.GEN_FUNC)
self.assertIs(loader.field_generator_kwargs, mock.sentinel.GEN_FUNC_KWARGS)
self.assertIs(loader.converter, mock.sentinel.CONVERTER)
assert loader.field_generator is mocker.sentinel.GEN_FUNC
assert loader.field_generator_kwargs is mocker.sentinel.GEN_FUNC_KWARGS
assert loader.converter is mocker.sentinel.CONVERTER

def test_normal_with_explicit_none(self):
with mock.patch("warnings.warn") as warn:
def test_normal_with_explicit_none(self, mocker):
with assert_no_warnings_regexp():
loader = Loader(
mock.sentinel.GEN_FUNC,
mock.sentinel.GEN_FUNC_KWARGS,
mock.sentinel.CONVERTER,
mocker.sentinel.GEN_FUNC,
mocker.sentinel.GEN_FUNC_KWARGS,
mocker.sentinel.CONVERTER,
)
self.assertEqual(warn.call_count, 0)
self.assertIs(loader.field_generator, mock.sentinel.GEN_FUNC)
self.assertIs(loader.field_generator_kwargs, mock.sentinel.GEN_FUNC_KWARGS)
self.assertIs(loader.converter, mock.sentinel.CONVERTER)


if __name__ == "__main__":
tests.main()
assert loader.field_generator is mocker.sentinel.GEN_FUNC
assert loader.field_generator_kwargs is mocker.sentinel.GEN_FUNC_KWARGS
assert loader.converter is mocker.sentinel.CONVERTER
25 changes: 6 additions & 19 deletions lib/iris/tests/unit/fileformats/rules/test__make_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,15 @@
# 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 :func:`iris.fileformats.rules._make_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 warnings

import numpy as np
import pytest

from iris.fileformats.rules import ConversionMetadata, _make_cube


class Test(tests.IrisTest):
class Test:
def test_invalid_units(self):
# Mock converter() function that returns an invalid
# units string amongst the collection of other elements.
Expand Down Expand Up @@ -46,20 +41,12 @@ def test_invalid_units(self):
field = mock.Mock(
core_data=lambda: data, bmdi=9999.0, realised_dtype=data.dtype
)
with warnings.catch_warnings(record=True) as warn:
warnings.simplefilter("always")

exp_emsg = "invalid units {!r}".format(units)
with pytest.warns(match=exp_emsg):
cube, factories, references = _make_cube(field, converter)

# Check attributes dictionary is correctly populated.
expected_attributes = attributes.copy()
expected_attributes["invalid_units"] = units
self.assertEqual(cube.attributes, expected_attributes)

# Check warning was raised.
self.assertEqual(len(warn), 1)
exp_emsg = "invalid units {!r}".format(units)
self.assertRegex(str(warn[0]), exp_emsg)


if __name__ == "__main__":
tests.main()
assert cube.attributes == expected_attributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@
# 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.
"""Test iris.fileformats.rules.py - metadata translation rules."""

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

import types
from unittest import mock

import numpy as np
import pytest

from iris.aux_factory import HybridHeightFactory
from iris.coords import CellMethod
Expand All @@ -26,30 +22,31 @@
load_cubes,
scalar_cell_method,
)
from iris.tests._shared_utils import skip_data
import iris.tests.stock as stock


class TestConcreteReferenceTarget(tests.IrisTest):
class TestConcreteReferenceTarget:
def test_attributes(self):
with self.assertRaises(TypeError):
with pytest.raises(TypeError):
target = ConcreteReferenceTarget()

target = ConcreteReferenceTarget("foo")
self.assertEqual(target.name, "foo")
self.assertIsNone(target.transform)
assert target.name == "foo"
assert target.transform is None

def transform(_):
return _

target = ConcreteReferenceTarget("foo", transform)
self.assertEqual(target.name, "foo")
self.assertIs(target.transform, transform)
assert target.name == "foo"
assert target.transform is transform

def test_single_cube_no_transform(self):
target = ConcreteReferenceTarget("foo")
src = stock.simple_2d()
target.add_cube(src)
self.assertIs(target.as_cube(), src)
assert target.as_cube() is src

def test_single_cube_with_transform(self):
def transform(cube):
Expand All @@ -59,22 +56,22 @@ def transform(cube):
src = stock.simple_2d()
target.add_cube(src)
dest = target.as_cube()
self.assertEqual(dest.long_name, "wibble")
self.assertNotEqual(dest, src)
assert dest.long_name == "wibble"
assert dest != src
dest.long_name = src.long_name
self.assertEqual(dest, src)
assert dest == src

@tests.skip_data
@skip_data
def test_multiple_cubes_no_transform(self):
target = ConcreteReferenceTarget("foo")
src = stock.realistic_4d()
for i in range(src.shape[0]):
target.add_cube(src[i])
dest = target.as_cube()
self.assertIsNot(dest, src)
self.assertEqual(dest, src)
assert dest is not src
assert dest == src

@tests.skip_data
@skip_data
def test_multiple_cubes_with_transform(self):
def transform(cube):
return {"long_name": "wibble"}
Expand All @@ -84,13 +81,13 @@ def transform(cube):
for i in range(src.shape[0]):
target.add_cube(src[i])
dest = target.as_cube()
self.assertEqual(dest.long_name, "wibble")
self.assertNotEqual(dest, src)
assert dest.long_name == "wibble"
assert dest != src
dest.long_name = src.long_name
self.assertEqual(dest, src)
assert dest == src


class TestLoadCubes(tests.IrisTest):
class TestLoadCubes:
def test_simple_factory(self):
# Test the creation process for a factory definition which only
# uses simple dict arguments.
Expand Down Expand Up @@ -124,7 +121,7 @@ def converter(field):
cubes = load_cubes(["fake_filename"], None, fake_loader)

# Check the result is a generator with a single entry.
self.assertIsInstance(cubes, types.GeneratorType)
assert isinstance(cubes, types.GeneratorType)
try:
# Suppress the normal Cube.coord() and Cube.add_aux_factory()
# methods.
Expand All @@ -139,15 +136,15 @@ def converter(field):
finally:
Cube.coord = coord_method
Cube.add_aux_factory = add_aux_factory_method
self.assertEqual(len(cubes), 1)
assert len(cubes) == 1
# Check the "cube" has an "aux_factory" added, which itself
# must have been created with the correct arguments.
self.assertTrue(hasattr(cubes[0], "fake_aux_factory"))
self.assertIs(cubes[0].fake_aux_factory, aux_factory)
self.assertTrue(hasattr(aux_factory, "fake_args"))
self.assertEqual(aux_factory.fake_args, ({"name": "foo"},))
assert hasattr(cubes[0], "fake_aux_factory")
assert cubes[0].fake_aux_factory is aux_factory
assert hasattr(aux_factory, "fake_args")
assert aux_factory.fake_args == ({"name": "foo"},)

@tests.skip_data
@skip_data
def test_cross_reference(self):
# Test the creation process for a factory definition which uses
# a cross-reference.
Expand Down Expand Up @@ -219,42 +216,38 @@ def converter(field):
cubes = load_cubes(["fake_filename"], None, fake_loader)

# Check the result is a generator containing two Cubes.
self.assertIsInstance(cubes, types.GeneratorType)
assert isinstance(cubes, types.GeneratorType)
cubes = list(cubes)
self.assertEqual(len(cubes), 2)
assert len(cubes) == 2
# Check the "cube" has an "aux_factory" added, which itself
# must have been created with the correct arguments.
self.assertEqual(len(cubes[1].aux_factories), 1)
self.assertEqual(len(cubes[1].coords("surface_altitude")), 1)
assert len(cubes[1].aux_factories) == 1
assert len(cubes[1].coords("surface_altitude")) == 1


class Test_scalar_cell_method(tests.IrisTest):
class Test_scalar_cell_method:
"""Tests for iris.fileformats.rules.scalar_cell_method() function."""

def setUp(self):
def setup_method(self):
self.cube = stock.simple_2d()
self.cm = CellMethod("mean", "foo", "1 hour")
self.cube.cell_methods = (self.cm,)

def test_cell_method_found(self):
actual = scalar_cell_method(self.cube, "mean", "foo")
self.assertEqual(actual, self.cm)
assert actual == self.cm

def test_method_different(self):
actual = scalar_cell_method(self.cube, "average", "foo")
self.assertIsNone(actual)
assert actual is None

def test_coord_name_different(self):
actual = scalar_cell_method(self.cube, "average", "bar")
self.assertIsNone(actual)
assert actual is None

def test_double_coord_fails(self):
self.cube.cell_methods = (
CellMethod("mean", ("foo", "bar"), ("1 hour", "1 hour")),
)
actual = scalar_cell_method(self.cube, "mean", "foo")
self.assertIsNone(actual)


if __name__ == "__main__":
tests.main()
assert actual is None

0 comments on commit 73926d2

Please sign in to comment.