Coverage for tests/test_apdbMetricTask.py : 33%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of verify.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22import shutil
23import tempfile
24import unittest.mock
26import astropy.units as u
28import lsst.utils.tests
29from lsst.pex.config import Config
30import lsst.daf.butler.tests as butlerTests
31from lsst.pipe.base import Task, Struct, testUtils
33from lsst.verify import Measurement
34from lsst.verify.tasks import ApdbMetricTask, MetricComputationError
35from lsst.verify.tasks.testUtils import ApdbMetricTestCase
38class DummyTask(ApdbMetricTask):
39 _DefaultName = "NotARealTask"
41 def makeMeasurement(self, _dbHandle, outputDataId):
42 if outputDataId:
43 nChars = len(outputDataId["instrument"])
44 return Measurement(self.config.metricName,
45 nChars * u.dimensionless_unscaled)
46 else:
47 return Measurement(self.config.metricName,
48 0 * u.dimensionless_unscaled)
51class Gen3ApdbTestSuite(ApdbMetricTestCase):
52 @classmethod
53 def makeTask(cls):
54 class MockDbLoader(Task):
55 ConfigClass = Config
57 def run(self, _):
58 return Struct(apdb=unittest.mock.Mock())
60 config = DummyTask.ConfigClass()
61 config.dbLoader.retarget(MockDbLoader)
62 config.connections.package = "verify"
63 config.connections.metric = "DummyApdb"
64 config.validate()
65 return DummyTask(config=config)
67 @classmethod
68 def setUpClass(cls):
69 super().setUpClass()
71 cls.CAMERA_ID = "NotACam"
72 cls.VISIT_ID = 42
73 cls.CHIP_ID = 5
75 # makeTestRepo called in setUpClass because it's *very* slow
76 cls.root = tempfile.mkdtemp()
77 cls.repo = butlerTests.makeTestRepo(cls.root, {
78 "instrument": [cls.CAMERA_ID],
79 "visit": [cls.VISIT_ID],
80 "detector": [cls.CHIP_ID],
81 })
83 # self.task not visible at class level
84 task = cls.makeTask()
85 connections = task.config.ConnectionsClass(config=task.config)
87 butlerTests.addDatasetType(
88 cls.repo,
89 connections.measurement.name,
90 connections.measurement.dimensions,
91 connections.measurement.storageClass)
92 butlerTests.addDatasetType(
93 cls.repo,
94 connections.dbInfo.name,
95 connections.dbInfo.dimensions,
96 connections.dbInfo.storageClass)
98 @classmethod
99 def tearDownClass(cls):
100 shutil.rmtree(cls.root, ignore_errors=True)
101 super().tearDownClass()
103 def setUp(self):
104 super().setUp()
106 self.connections = self.task.config.ConnectionsClass(
107 config=self.task.config)
109 def _prepareQuantum(self, task):
110 inputId = {
111 "instrument": self.CAMERA_ID,
112 "visit": self.VISIT_ID,
113 "detector": self.CHIP_ID,
114 }
116 butler = butlerTests.makeTestCollection(self.repo)
117 # task.config not persistable if it refers to a local class
118 # We don't actually use the persisted config, so just make a new one
119 info = task.ConfigClass()
120 butler.put(info, "apdb_marker", inputId)
122 quantum = testUtils.makeQuantum(
123 task, butler, inputId,
124 {"dbInfo": [inputId], "measurement": inputId})
126 return (butler, quantum, info)
128 def testRunQuantum(self):
129 butler, quantum, input = self._prepareQuantum(self.task)
131 run = testUtils.runTestQuantum(self.task, butler, quantum)
133 # Did output data ID get passed to DummyTask.run?
134 expectedId = lsst.daf.butler.DataCoordinate.standardize(
135 {"instrument": self.CAMERA_ID},
136 universe=butler.registry.dimensions)
137 run.assert_called_once_with(
138 dbInfo=[input],
139 outputDataId=expectedId)
141 def testRunQuantumNone(self):
142 class NoneTask(DummyTask):
143 def run(self, *args, **kwargs):
144 return Struct(measurement=None)
146 config = NoneTask.ConfigClass()
147 config.connections.package = "verify"
148 config.connections.metric = "DummyApdb"
149 task = NoneTask(config=config)
150 butler, quantum, input = self._prepareQuantum(task)
152 with unittest.mock.patch.object(
153 lsst.pipe.base.ButlerQuantumContext, "put") as put:
154 testUtils.runTestQuantum(task, butler, quantum, mockRun=False)
155 # Should not attempt to write nonexistent data
156 put.assert_not_called()
158 def testRunQuantumException(self):
159 class ExceptionalTask(DummyTask):
160 def run(self, *args, **kwargs):
161 raise MetricComputationError()
163 config = ExceptionalTask.ConfigClass()
164 config.connections.package = "verify"
165 config.connections.metric = "DummyApdb"
166 task = ExceptionalTask(config=config)
167 butler, quantum, input = self._prepareQuantum(task)
169 with unittest.mock.patch.object(
170 lsst.pipe.base.ButlerQuantumContext, "put") as put:
171 testUtils.runTestQuantum(task, butler, quantum, mockRun=False)
172 # Should not propagate MetricComputationError
173 # Should not attempt to write data that was never returned
174 put.assert_not_called()
177# Hack around unittest's hacky test setup system
178del ApdbMetricTestCase
181class MemoryTester(lsst.utils.tests.MemoryTestCase):
182 pass
185def setup_module(module):
186 lsst.utils.tests.init()
189if __name__ == "__main__": 189 ↛ 190line 189 didn't jump to line 190, because the condition on line 189 was never true
190 lsst.utils.tests.init()
191 unittest.main()