From 2496c6be9d3e73378fdf555436f5fb214af762ce Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 9 Dec 2022 14:33:18 +0000 Subject: [PATCH 1/4] remove test timings --- lib/iris/tests/__init__.py | 78 +------------------ lib/iris/tests/test_plot.py | 6 +- .../maths/test__arith__derived_coords.py | 3 +- .../analysis/maths/test__arith__meshcoords.py | 6 +- .../tests/unit/analysis/maths/test_add.py | 11 +-- .../tests/unit/analysis/maths/test_divide.py | 8 +- .../unit/analysis/maths/test_multiply.py | 11 +-- .../unit/analysis/maths/test_subtract.py | 11 +-- lib/iris/tests/unit/merge/test_ProtoCube.py | 42 +++------- lib/iris/tests/unit/tests/test_IrisTest.py | 8 +- 10 files changed, 31 insertions(+), 153 deletions(-) diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index 4840de8cdb..cdc6afbb78 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -16,7 +16,6 @@ import collections from collections.abc import Mapping import contextlib -import datetime import difflib import filecmp import functools @@ -208,7 +207,7 @@ def assert_masked_array_almost_equal(a, b, decimal=6, strict=False): ) -class IrisTest_nometa(unittest.TestCase): +class IrisTest(unittest.TestCase): """A subclass of unittest.TestCase which provides Iris specific testing functionality.""" _assertion_counts = collections.defaultdict(int) @@ -937,80 +936,10 @@ def assertEqualAndKind(self, value, expected): ) -# An environment variable controls whether test timings are output. -# -# NOTE: to run tests with timing output, nosetests cannot be used. -# At present, that includes not using "python setup.py test" -# The typically best way is like this : -# $ export IRIS_TEST_TIMINGS=1 -# $ python -m unittest discover -s iris.tests -# and commonly adding ... -# | grep "TIMING TEST" >iris_test_output.txt -# -_PRINT_TEST_TIMINGS = bool(int(os.environ.get("IRIS_TEST_TIMINGS", 0))) - - def _method_path(meth, cls): return ".".join([cls.__module__, cls.__name__, meth.__name__]) -def _testfunction_timing_decorator(fn, cls): - # Function decorator for making a testcase print its execution time. - @functools.wraps(fn) - def inner(*args, **kwargs): - start_time = datetime.datetime.now() - try: - result = fn(*args, **kwargs) - finally: - end_time = datetime.datetime.now() - elapsed_time = (end_time - start_time).total_seconds() - msg = '\n TEST TIMING -- "{}" took : {:12.6f} sec.' - name = _method_path(fn, cls) - print(msg.format(name, elapsed_time)) - return result - - return inner - - -def iristest_timing_decorator(cls): - # Class decorator to make all "test_.." functions print execution timings. - if _PRINT_TEST_TIMINGS: - # NOTE: 'dir' scans *all* class properties, including inherited ones. - attr_names = dir(cls) - for attr_name in attr_names: - attr = getattr(cls, attr_name) - if callable(attr) and attr_name.startswith("test"): - attr = _testfunction_timing_decorator(attr, cls) - setattr(cls, attr_name, attr) - return cls - - -class _TestTimingsMetaclass(type): - # An alternative metaclass for IrisTest subclasses, which makes - # them print execution timings for all the testcases. - # This is equivalent to applying the @iristest_timing_decorator to - # every test class that inherits from IrisTest. - # NOTE: however, it means you *cannot* specify a different metaclass for - # your test class inheriting from IrisTest. - # See below for how to solve that where needed. - def __new__(cls, clsname, base_classes, attrs): - result = type.__new__(cls, clsname, base_classes, attrs) - if _PRINT_TEST_TIMINGS: - result = iristest_timing_decorator(result) - return result - - -class IrisTest(IrisTest_nometa, metaclass=_TestTimingsMetaclass): - # Derive the 'ordinary' IrisTest from IrisTest_nometa, but add the - # metaclass that enables test timings output. - # This means that all subclasses also get the timing behaviour. - # However, if a different metaclass is *wanted* for an IrisTest subclass, - # this would cause a metaclass conflict. - # Instead, you can inherit from IrisTest_nometa and apply the - # @iristest_timing_decorator explicitly to your new testclass. - pass - - get_data_path = IrisTest.get_data_path get_result_path = IrisTest.get_result_path @@ -1019,11 +948,6 @@ class GraphicsTest(graphics.GraphicsTestMixin, IrisTest): pass -class GraphicsTest_nometa(graphics.GraphicsTestMixin, IrisTest_nometa): - # Graphicstest without the metaclass providing test timings. - pass - - def skip_data(fn): """ Decorator to choose whether to run tests, based on the availability of diff --git a/lib/iris/tests/test_plot.py b/lib/iris/tests/test_plot.py index 77aea2b6b6..c9eba31e58 100644 --- a/lib/iris/tests/test_plot.py +++ b/lib/iris/tests/test_plot.py @@ -712,9 +712,8 @@ def override_with_decorated_methods(attr_dict, target_dict, decorator): @tests.skip_data -@tests.iristest_timing_decorator class TestPcolorNoBounds( - tests.GraphicsTest_nometa, SliceMixin, metaclass=CheckForWarningsMetaclass + tests.GraphicsTest, SliceMixin, metaclass=CheckForWarningsMetaclass ): """ Test the iris.plot.pcolor routine on a cube with coordinates @@ -729,9 +728,8 @@ def setUp(self): @tests.skip_data -@tests.iristest_timing_decorator class TestPcolormeshNoBounds( - tests.GraphicsTest_nometa, SliceMixin, metaclass=CheckForWarningsMetaclass + tests.GraphicsTest, SliceMixin, metaclass=CheckForWarningsMetaclass ): """ Test the iris.plot.pcolormesh routine on a cube with coordinates diff --git a/lib/iris/tests/unit/analysis/maths/test__arith__derived_coords.py b/lib/iris/tests/unit/analysis/maths/test__arith__derived_coords.py index 51f71affb0..57e012e1c9 100644 --- a/lib/iris/tests/unit/analysis/maths/test__arith__derived_coords.py +++ b/lib/iris/tests/unit/analysis/maths/test__arith__derived_coords.py @@ -16,9 +16,8 @@ @tests.skip_data -@tests.iristest_timing_decorator class TestBroadcastingDerived( - tests.IrisTest_nometa, + tests.IrisTest, MathsAddOperationMixin, CubeArithmeticBroadcastingTestMixin, ): diff --git a/lib/iris/tests/unit/analysis/maths/test__arith__meshcoords.py b/lib/iris/tests/unit/analysis/maths/test__arith__meshcoords.py index 1d81e7b480..e1255ef9d8 100644 --- a/lib/iris/tests/unit/analysis/maths/test__arith__meshcoords.py +++ b/lib/iris/tests/unit/analysis/maths/test__arith__meshcoords.py @@ -54,9 +54,8 @@ def _base_testcube(self): @tests.skip_data -@tests.iristest_timing_decorator class TestBroadcastingWithMesh( - tests.IrisTest_nometa, + tests.IrisTest, MeshLocationsMixin, MathsAddOperationMixin, CubeArithmeticBroadcastingTestMixin, @@ -71,9 +70,8 @@ class TestBroadcastingWithMesh( @tests.skip_data -@tests.iristest_timing_decorator class TestBroadcastingWithMeshAndDerived( - tests.IrisTest_nometa, + tests.IrisTest, MeshLocationsMixin, MathsAddOperationMixin, CubeArithmeticBroadcastingTestMixin, diff --git a/lib/iris/tests/unit/analysis/maths/test_add.py b/lib/iris/tests/unit/analysis/maths/test_add.py index 77dd7877bf..1ca7f7c244 100644 --- a/lib/iris/tests/unit/analysis/maths/test_add.py +++ b/lib/iris/tests/unit/analysis/maths/test_add.py @@ -21,10 +21,7 @@ @tests.skip_data -@tests.iristest_timing_decorator -class TestBroadcasting( - tests.IrisTest_nometa, CubeArithmeticBroadcastingTestMixin -): +class TestBroadcasting(tests.IrisTest, CubeArithmeticBroadcastingTestMixin): @property def data_op(self): return operator.add @@ -34,8 +31,7 @@ def cube_func(self): return add -@tests.iristest_timing_decorator -class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): +class TestMasking(tests.IrisTest, CubeArithmeticMaskingTestMixin): @property def data_op(self): return operator.add @@ -57,9 +53,8 @@ def test_reversed_points(self): add(cube1, cube2) -@tests.iristest_timing_decorator class TestMaskedConstant( - tests.IrisTest_nometa, CubeArithmeticMaskedConstantTestMixin + tests.IrisTest, CubeArithmeticMaskedConstantTestMixin ): @property def data_op(self): diff --git a/lib/iris/tests/unit/analysis/maths/test_divide.py b/lib/iris/tests/unit/analysis/maths/test_divide.py index 1763f223b0..4bd202e037 100644 --- a/lib/iris/tests/unit/analysis/maths/test_divide.py +++ b/lib/iris/tests/unit/analysis/maths/test_divide.py @@ -23,10 +23,7 @@ @tests.skip_data -@tests.iristest_timing_decorator -class TestBroadcasting( - tests.IrisTest_nometa, CubeArithmeticBroadcastingTestMixin -): +class TestBroadcasting(tests.IrisTest, CubeArithmeticBroadcastingTestMixin): @property def data_op(self): return operator.truediv @@ -36,8 +33,7 @@ def cube_func(self): return divide -@tests.iristest_timing_decorator -class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): +class TestMasking(tests.IrisTest, CubeArithmeticMaskingTestMixin): @property def data_op(self): return operator.truediv diff --git a/lib/iris/tests/unit/analysis/maths/test_multiply.py b/lib/iris/tests/unit/analysis/maths/test_multiply.py index 600593c64b..266342605a 100644 --- a/lib/iris/tests/unit/analysis/maths/test_multiply.py +++ b/lib/iris/tests/unit/analysis/maths/test_multiply.py @@ -21,10 +21,7 @@ @tests.skip_data -@tests.iristest_timing_decorator -class TestBroadcasting( - tests.IrisTest_nometa, CubeArithmeticBroadcastingTestMixin -): +class TestBroadcasting(tests.IrisTest, CubeArithmeticBroadcastingTestMixin): @property def data_op(self): return operator.mul @@ -34,8 +31,7 @@ def cube_func(self): return multiply -@tests.iristest_timing_decorator -class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): +class TestMasking(tests.IrisTest, CubeArithmeticMaskingTestMixin): @property def data_op(self): return operator.mul @@ -57,9 +53,8 @@ def test_reversed_points(self): multiply(cube1, cube2) -@tests.iristest_timing_decorator class TestMaskedConstant( - tests.IrisTest_nometa, CubeArithmeticMaskedConstantTestMixin + tests.IrisTest, CubeArithmeticMaskedConstantTestMixin ): @property def data_op(self): diff --git a/lib/iris/tests/unit/analysis/maths/test_subtract.py b/lib/iris/tests/unit/analysis/maths/test_subtract.py index 964e8c04c7..f7a9df34d0 100644 --- a/lib/iris/tests/unit/analysis/maths/test_subtract.py +++ b/lib/iris/tests/unit/analysis/maths/test_subtract.py @@ -21,10 +21,7 @@ @tests.skip_data -@tests.iristest_timing_decorator -class TestBroadcasting( - tests.IrisTest_nometa, CubeArithmeticBroadcastingTestMixin -): +class TestBroadcasting(tests.IrisTest, CubeArithmeticBroadcastingTestMixin): @property def data_op(self): return operator.sub @@ -34,8 +31,7 @@ def cube_func(self): return subtract -@tests.iristest_timing_decorator -class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin): +class TestMasking(tests.IrisTest, CubeArithmeticMaskingTestMixin): @property def data_op(self): return operator.sub @@ -57,9 +53,8 @@ def test_reversed_points(self): subtract(cube1, cube2) -@tests.iristest_timing_decorator class TestMaskedConstant( - tests.IrisTest_nometa, CubeArithmeticMaskedConstantTestMixin + tests.IrisTest, CubeArithmeticMaskedConstantTestMixin ): @property def data_op(self): diff --git a/lib/iris/tests/unit/merge/test_ProtoCube.py b/lib/iris/tests/unit/merge/test_ProtoCube.py index 31b1efb3fd..625290ad24 100644 --- a/lib/iris/tests/unit/merge/test_ProtoCube.py +++ b/lib/iris/tests/unit/merge/test_ProtoCube.py @@ -77,8 +77,7 @@ def test_error(self): self.assertTrue(result) -@tests.iristest_timing_decorator -class Test_register__match(Mixin_register, tests.IrisTest_nometa): +class Test_register__match(Mixin_register, tests.IrisTest): @property def fragments(self): return [] @@ -88,8 +87,7 @@ def cube2(self): return example_cube() -@tests.iristest_timing_decorator -class Test_register__standard_name(Mixin_register, tests.IrisTest_nometa): +class Test_register__standard_name(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.standard_name", "air_temperature", "air_density"] @@ -101,8 +99,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__long_name(Mixin_register, tests.IrisTest_nometa): +class Test_register__long_name(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.long_name", "screen_air_temp", "Belling"] @@ -114,8 +111,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__var_name(Mixin_register, tests.IrisTest_nometa): +class Test_register__var_name(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.var_name", "'airtemp'", "'airtemp2'"] @@ -127,8 +123,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__units(Mixin_register, tests.IrisTest_nometa): +class Test_register__units(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.units", "'K'", "'C'"] @@ -140,8 +135,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__attributes_unequal(Mixin_register, tests.IrisTest_nometa): +class Test_register__attributes_unequal(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.attributes", "'mint'"] @@ -153,10 +147,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__attributes_unequal_array( - Mixin_register, tests.IrisTest_nometa -): +class Test_register__attributes_unequal_array(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.attributes", "'mint'"] @@ -174,10 +165,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__attributes_superset( - Mixin_register, tests.IrisTest_nometa -): +class Test_register__attributes_superset(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.attributes", "'stuffed'"] @@ -189,10 +177,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__attributes_multi_diff( - Mixin_register, tests.IrisTest_nometa -): +class Test_register__attributes_multi_diff(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.attributes", "'sam'", "'mint'"] @@ -215,8 +200,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__cell_method(Mixin_register, tests.IrisTest_nometa): +class Test_register__cell_method(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.cell_methods"] @@ -228,8 +212,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__data_shape(Mixin_register, tests.IrisTest_nometa): +class Test_register__data_shape(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube.shape", "(2,)", "(3,)"] @@ -241,8 +224,7 @@ def cube2(self): return cube -@tests.iristest_timing_decorator -class Test_register__data_dtype(Mixin_register, tests.IrisTest_nometa): +class Test_register__data_dtype(Mixin_register, tests.IrisTest): @property def fragments(self): return ["cube data dtype", "int32", "int8"] diff --git a/lib/iris/tests/unit/tests/test_IrisTest.py b/lib/iris/tests/unit/tests/test_IrisTest.py index 5725b59d40..10de2a7760 100644 --- a/lib/iris/tests/unit/tests/test_IrisTest.py +++ b/lib/iris/tests/unit/tests/test_IrisTest.py @@ -66,8 +66,7 @@ def test_different_mask_nonstrict(self): self._func(self.arr1, arr2, strict=False) -@tests.iristest_timing_decorator -class Test_assertMaskedArrayEqual(_MaskedArrayEquality, tests.IrisTest_nometa): +class Test_assertMaskedArrayEqual(_MaskedArrayEquality, tests.IrisTest): @property def _func(self): return self.assertMaskedArrayEqual @@ -114,10 +113,7 @@ def test_masked_nonmasked_same_emptymask(self): self.assertMaskedArrayEqual(arr1, arr2) -@tests.iristest_timing_decorator -class Test_assertMaskedArrayAlmostEqual( - _MaskedArrayEquality, tests.IrisTest_nometa -): +class Test_assertMaskedArrayAlmostEqual(_MaskedArrayEquality, tests.IrisTest): @property def _func(self): return self.assertMaskedArrayAlmostEqual From 5487a1650eb4b71f77bfa91cd21ce07664e173eb Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 9 Dec 2022 14:51:22 +0000 Subject: [PATCH 2/4] whatsnew --- docs/src/whatsnew/latest.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/src/whatsnew/latest.rst b/docs/src/whatsnew/latest.rst index bf5e942601..f3406cc831 100644 --- a/docs/src/whatsnew/latest.rst +++ b/docs/src/whatsnew/latest.rst @@ -76,6 +76,9 @@ This document explains the changes made to Iris for this release #. `@fnattino`_ changed the order of ``ncgen`` arguments in the command to create NetCDF files for testing (caused errors on OS X). (:pull:`5105`) +#. `@rcomer`_ removed some old infrastructure that printed test timings. + (:pull:`5101`) + .. comment Whatsnew author names (@github name) in alphabetical order. Note that, From 637893c3730a7e027bd7f9d30878a2bc2f19945c Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 9 Dec 2022 15:33:02 +0000 Subject: [PATCH 3/4] missed a bit --- lib/iris/tests/__init__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index cdc6afbb78..5529b899c5 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -936,10 +936,6 @@ def assertEqualAndKind(self, value, expected): ) -def _method_path(meth, cls): - return ".".join([cls.__module__, cls.__name__, meth.__name__]) - - get_data_path = IrisTest.get_data_path get_result_path = IrisTest.get_result_path From d3ad08c68a452f3c6fb8db168784e74c7873b95d Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 14 Dec 2022 14:59:07 +0000 Subject: [PATCH 4/4] review action --- lib/iris/tests/graphics/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/iris/tests/graphics/README.md b/lib/iris/tests/graphics/README.md index b26f1720e8..069fc01f70 100755 --- a/lib/iris/tests/graphics/README.md +++ b/lib/iris/tests/graphics/README.md @@ -24,7 +24,7 @@ perceived as it may be a simple pixel shift. ## Testing Strategy -The `iris.tests.IrisTest_nometa.check_graphic` test routine calls out to +The `iris.tests.IrisTest.check_graphic` test routine calls out to `iris.tests.graphics.check_graphic` which tests against the **acceptable** result. It does this using an image **hash** comparison technique which allows us to be robust against minor variations based on underlying library updates.