Coverage for python/lsst/verify/gen2tasks/testUtils.py: 46%
36 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-16 10:09 +0000
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-16 10:09 +0000
1#
2# This file is part of verify.
3#
4# Developed for the LSST Data Management System.
5# This product includes software developed by the LSST Project
6# (http://www.lsst.org).
7# See the COPYRIGHT file at the top-level directory of this distribution
8# for details of code ownership.
9#
10# This program is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program. If not, see <http://www.gnu.org/licenses/>.
22#
24__all__ = ["MetricTaskTestCase"]
26import abc
27import unittest.mock
28import inspect
30import lsst.utils.tests
32from lsst.pipe.base import Struct
33from lsst.verify import Measurement
36class MetricTaskTestCase(lsst.utils.tests.TestCase, metaclass=abc.ABCMeta):
37 """Unit test base class for tests of `tasks.MetricTask`.
39 This class provides tests of the generic ``MetricTask`` API. Subclasses
40 must override `taskFactory`, and may add extra tests for class-specific
41 functionality. If subclasses override `setUp`, they must call
42 `MetricTaskTestCase.setUp`.
43 """
44 @classmethod
45 @abc.abstractmethod
46 def makeTask(cls):
47 """Construct the task to be tested.
49 This overridable method will be called during test setup.
51 Returns
52 -------
53 task : `lsst.verify.tasks.MetricTask`
54 A new MetricTask object to test.
55 """
57 task = None
58 """The ``MetricTask`` being tested by this object
59 (`tasks.MetricTask`).
61 This attribute is initialized automatically.
62 """
64 taskClass = None
65 """The type of `task` (`tasks.MetricTask`-type).
67 This attribute is initialized automatically.
68 """
70 def setUp(self):
71 """Setup common to all MetricTask tests.
73 Notes
74 -----
75 This implementation calls `taskFactory`, then initializes `task`
76 and `taskClass`.
77 """
78 self.task = self.makeTask()
79 self.taskClass = type(self.task)
81 # Implementation classes will override run. Can't implement most tests if
82 # it's mocked, risk excessive runtime if it isn't.
84 def testInputDatasetTypesKeys(self):
85 defaultInputs = self.taskClass.getInputDatasetTypes(self.task.config)
86 runParams = inspect.signature(self.taskClass.run).parameters
87 # Filter out keywords with defaults
88 runParams = {name: param for name, param in runParams.items()
89 if param.default is param.empty}
91 # Only way to check if run has been overridden?
92 if runParams.keys() != ['kwargs']:
93 self.assertSetEqual(
94 set(defaultInputs.keys()).union({'self'}),
95 set(runParams.keys()).union({'self'}),
96 "getInputDatasetTypes keys do not match run parameters")
98 def testAddStandardMetadata(self):
99 measurement = Measurement('foo.bar', 0.0)
100 dataId = {'tract': 42, 'patch': 3, 'filter': 'Ic'}
101 self.task.addStandardMetadata(measurement, dataId)
102 # Nothing to test until addStandardMetadata adds something
104 def testCallAddStandardMetadata(self):
105 dummy = Measurement('foo.bar', 0.0)
106 with unittest.mock.patch.multiple(
107 self.taskClass, autospec=True,
108 run=unittest.mock.DEFAULT,
109 addStandardMetadata=unittest.mock.DEFAULT) as mockDict:
110 mockDict['run'].return_value = Struct(measurement=dummy)
112 inputScalars = self.taskClass.areInputDatasetsScalar(
113 self.task.config)
114 # Probably won't satisfy all adaptArgsAndRun specs,
115 # but hopefully works with most of them
116 dataId = {}
117 result = self.task.adaptArgsAndRun(
118 {key: (None if scalar else [None])
119 for key, scalar in inputScalars.items()},
120 {key: (dataId if scalar else [dataId])
121 for key, scalar in inputScalars.items()},
122 {'measurement': dataId})
123 mockDict['addStandardMetadata'].assert_called_once_with(
124 self.task, result.measurement, dataId)