Skip to content

Commit

Permalink
Revise naming + add a usage description.
Browse files Browse the repository at this point in the history
  • Loading branch information
pp-mo committed Feb 14, 2017
1 parent 90d4465 commit e520f14
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 75 deletions.
38 changes: 23 additions & 15 deletions lib/iris/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def get_data_path(relative_path):
return data_path


class _IrisTest_nometa(unittest.TestCase):
class IrisTest_nometa(unittest.TestCase):
"""A subclass of unittest.TestCase which provides Iris specific testing functionality."""

_assertion_counts = collections.defaultdict(int)
Expand Down Expand Up @@ -855,6 +855,15 @@ def assertArrayShapeStats(self, result, shape, mean, std_dev, rtol=1e-6):


# 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)))


Expand All @@ -863,7 +872,7 @@ def _method_path(meth):
return '.'.join([cls.__module__, cls.__name__, meth.__name__])


def _test_timings_function_decorator(fn):
def _testfunction_timing_decorator(fn):
# Function decorator for making a testcase print its execution time.
@functools.wraps(fn)
def inner(*args, **kwargs):
Expand All @@ -880,44 +889,43 @@ def inner(*args, **kwargs):
return inner


def _test_timings_class_decorator(cls):
def iristest_timing_decorator(cls):
# Class decorator to make all "test_.." functions print execution timings.
if _PRINT_TEST_TIMINGS:
# NOTE: 'dir' hits *all* function properties, including inherited ones.
# 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 = _test_timings_function_decorator(attr)
attr = _testfunction_timing_decorator(attr)
setattr(cls, attr_name, attr)
return cls


class TestTimingsMetaclass(type):
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 @_test_timings_class_decorator to
# 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 = _test_timings_class_decorator(result)
result = iristest_timing_decorator(result)
return result


class IrisTest(_IrisTest_nometa):
# Derive the 'ordinary' IrisTest from _IrisTest_nometa, but add the
class IrisTest(six.with_metaclass(_TestTimingsMetaclass, IrisTest_nometa)):
# 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
# @_test_timings_class_decorator explicitly to your new testclass.
if _PRINT_TEST_TIMINGS:
__metaclass__ = TestTimingsMetaclass
# Instead, you can inherit from IrisTest_nometa and apply the
# @iristest_timing_decorator explicitly to your new testclass.
pass


get_result_path = IrisTest.get_result_path
Expand Down Expand Up @@ -950,7 +958,7 @@ class GraphicsTest(GraphicsTestMixin, IrisTest):
pass


class GraphicsTest_nometa(GraphicsTestMixin, _IrisTest_nometa):
class GraphicsTest_nometa(GraphicsTestMixin, IrisTest_nometa):
# Graphicstest without the metaclass providing test timings.
pass

Expand Down
4 changes: 2 additions & 2 deletions lib/iris/tests/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ def override_with_decorated_methods(attr_dict, target_dict,


@tests.skip_data
@tests._test_timings_class_decorator
@tests.iristest_timing_decorator
class TestPcolorNoBounds(six.with_metaclass(CheckForWarningsMetaclass,
tests.GraphicsTest_nometa,
SliceMixin)):
Expand All @@ -597,7 +597,7 @@ def setUp(self):


@tests.skip_data
@tests._test_timings_class_decorator
@tests.iristest_timing_decorator
class TestPcolormeshNoBounds(six.with_metaclass(CheckForWarningsMetaclass,
tests.GraphicsTest_nometa,
SliceMixin)):
Expand Down
8 changes: 4 additions & 4 deletions lib/iris/tests/unit/analysis/maths/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@


@tests.skip_data
@tests._test_timings_class_decorator
class TestBroadcasting(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class TestBroadcasting(tests.IrisTest_nometa,
CubeArithmeticBroadcastingTestMixin):
@property
def data_op(self):
Expand All @@ -43,8 +43,8 @@ def cube_func(self):
return add


@tests._test_timings_class_decorator
class TestMasking(tests._IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@tests.iristest_timing_decorator
class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@property
def data_op(self):
return operator.add
Expand Down
8 changes: 4 additions & 4 deletions lib/iris/tests/unit/analysis/maths/test_divide.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@


@tests.skip_data
@tests._test_timings_class_decorator
class TestBroadcasting(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class TestBroadcasting(tests.IrisTest_nometa,
CubeArithmeticBroadcastingTestMixin):
@property
def data_op(self):
Expand All @@ -48,8 +48,8 @@ def cube_func(self):
return divide


@tests._test_timings_class_decorator
class TestMasking(tests._IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@tests.iristest_timing_decorator
class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@property
def data_op(self):
try:
Expand Down
8 changes: 4 additions & 4 deletions lib/iris/tests/unit/analysis/maths/test_multiply.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@


@tests.skip_data
@tests._test_timings_class_decorator
class TestBroadcasting(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class TestBroadcasting(tests.IrisTest_nometa,
CubeArithmeticBroadcastingTestMixin):
@property
def data_op(self):
Expand All @@ -43,8 +43,8 @@ def cube_func(self):
return multiply


@tests._test_timings_class_decorator
class TestMasking(tests._IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@tests.iristest_timing_decorator
class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@property
def data_op(self):
return operator.mul
Expand Down
8 changes: 4 additions & 4 deletions lib/iris/tests/unit/analysis/maths/test_subtract.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@


@tests.skip_data
@tests._test_timings_class_decorator
class TestBroadcasting(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class TestBroadcasting(tests.IrisTest_nometa,
CubeArithmeticBroadcastingTestMixin):
@property
def data_op(self):
Expand All @@ -43,8 +43,8 @@ def cube_func(self):
return subtract


@tests._test_timings_class_decorator
class TestMasking(tests._IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@tests.iristest_timing_decorator
class TestMasking(tests.IrisTest_nometa, CubeArithmeticMaskingTestMixin):
@property
def data_op(self):
return operator.sub
Expand Down
28 changes: 14 additions & 14 deletions lib/iris/tests/unit/fileformats/grib/message/test_GribMessage.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,36 +211,36 @@ def _example_section_3(grib_definition_template_number, scanning_mode):
'Ni': 4}


@tests._test_timings_class_decorator
class Test_data__grid_template_0(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class Test_data__grid_template_0(tests.IrisTest_nometa,
Mixin_data__grid_template):
def section_3(self, scanning_mode):
return _example_section_3(0, scanning_mode)


@tests._test_timings_class_decorator
class Test_data__grid_template_1(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class Test_data__grid_template_1(tests.IrisTest_nometa,
Mixin_data__grid_template):
def section_3(self, scanning_mode):
return _example_section_3(1, scanning_mode)


@tests._test_timings_class_decorator
class Test_data__grid_template_5(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class Test_data__grid_template_5(tests.IrisTest_nometa,
Mixin_data__grid_template):
def section_3(self, scanning_mode):
return _example_section_3(5, scanning_mode)


@tests._test_timings_class_decorator
class Test_data__grid_template_12(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class Test_data__grid_template_12(tests.IrisTest_nometa,
Mixin_data__grid_template):
def section_3(self, scanning_mode):
return _example_section_3(12, scanning_mode)


@tests._test_timings_class_decorator
class Test_data__grid_template_30(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class Test_data__grid_template_30(tests.IrisTest_nometa,
Mixin_data__grid_template):
def section_3(self, scanning_mode):
section_3 = _example_section_3(30, scanning_mode)
Expand All @@ -252,15 +252,15 @@ def section_3(self, scanning_mode):
return section_3


@tests._test_timings_class_decorator
class Test_data__grid_template_40_regular(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class Test_data__grid_template_40_regular(tests.IrisTest_nometa,
Mixin_data__grid_template):
def section_3(self, scanning_mode):
return _example_section_3(40, scanning_mode)


@tests._test_timings_class_decorator
class Test_data__grid_template_90(tests._IrisTest_nometa,
@tests.iristest_timing_decorator
class Test_data__grid_template_90(tests.IrisTest_nometa,
Mixin_data__grid_template):
def section_3(self, scanning_mode):
section_3 = _example_section_3(90, scanning_mode)
Expand Down
Loading

0 comments on commit e520f14

Please sign in to comment.