Coverage for tests/test_apdbMetricTask.py: 35%

82 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-01-27 02:03 -0800

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/>. 

21 

22import shutil 

23import tempfile 

24import unittest.mock 

25 

26import astropy.units as u 

27 

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 

32 

33from lsst.verify import Measurement 

34from lsst.verify.tasks import ApdbMetricTask 

35from lsst.verify.tasks.testUtils import ApdbMetricTestCase 

36 

37 

38class DummyTask(ApdbMetricTask): 

39 _DefaultName = "NotARealTask" 

40 

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) 

49 

50 

51class Gen3ApdbTestSuite(ApdbMetricTestCase): 

52 @classmethod 

53 def makeTask(cls): 

54 class MockDbLoader(Task): 

55 ConfigClass = Config 

56 

57 def run(self, _): 

58 return Struct(apdb=unittest.mock.Mock()) 

59 

60 config = DummyTask.ConfigClass() 

61 config.dbLoader.retarget(MockDbLoader) 

62 config.connections.package = "verify" 

63 config.connections.metric = "DummyApdb" 

64 return DummyTask(config=config) 

65 

66 @classmethod 

67 def setUpClass(cls): 

68 super().setUpClass() 

69 

70 cls.CAMERA_ID = "NotACam" 

71 cls.VISIT_ID = 42 

72 cls.CHIP_ID = 5 

73 

74 # makeTestRepo called in setUpClass because it's *very* slow 

75 cls.root = tempfile.mkdtemp() 

76 cls.repo = butlerTests.makeTestRepo(cls.root, { 

77 "instrument": [cls.CAMERA_ID], 

78 "visit": [cls.VISIT_ID], 

79 "detector": [cls.CHIP_ID], 

80 }) 

81 

82 # self.task not visible at class level 

83 task = cls.makeTask() 

84 connections = task.config.ConnectionsClass(config=task.config) 

85 

86 butlerTests.addDatasetType( 

87 cls.repo, 

88 connections.measurement.name, 

89 connections.measurement.dimensions, 

90 connections.measurement.storageClass) 

91 butlerTests.addDatasetType( 

92 cls.repo, 

93 connections.dbInfo.name, 

94 connections.dbInfo.dimensions, 

95 connections.dbInfo.storageClass) 

96 

97 @classmethod 

98 def tearDownClass(cls): 

99 shutil.rmtree(cls.root, ignore_errors=True) 

100 super().tearDownClass() 

101 

102 def setUp(self): 

103 super().setUp() 

104 

105 self.connections = self.task.config.ConnectionsClass( 

106 config=self.task.config) 

107 

108 def _prepareQuantum(self, task): 

109 globalId = { 

110 "instrument": self.CAMERA_ID, 

111 } 

112 detectorId = { 

113 "instrument": self.CAMERA_ID, 

114 "visit": self.VISIT_ID, 

115 "detector": self.CHIP_ID, 

116 } 

117 

118 butler = butlerTests.makeTestCollection(self.repo) 

119 # task.config not persistable if it refers to a local class 

120 # We don't actually use the persisted config, so just make a new one 

121 info = task.ConfigClass() 

122 butler.put(info, "apdb_marker", detectorId) 

123 

124 quantum = testUtils.makeQuantum( 

125 task, butler, globalId, 

126 {"dbInfo": [detectorId], "measurement": globalId}) 

127 

128 return (butler, quantum, info) 

129 

130 def testRunQuantum(self): 

131 butler, quantum, input = self._prepareQuantum(self.task) 

132 

133 run = testUtils.runTestQuantum(self.task, butler, quantum) 

134 

135 # Did output data ID get passed to DummyTask.run? 

136 expectedId = lsst.daf.butler.DataCoordinate.standardize( 

137 {"instrument": self.CAMERA_ID}, 

138 universe=butler.registry.dimensions) 

139 run.assert_called_once_with( 

140 dbInfo=[input], 

141 outputDataId=expectedId) 

142 

143 def testRunQuantumNone(self): 

144 class NoneTask(DummyTask): 

145 def run(self, *args, **kwargs): 

146 return Struct(measurement=None) 

147 

148 config = NoneTask.ConfigClass() 

149 config.connections.package = "verify" 

150 config.connections.metric = "DummyApdb" 

151 task = NoneTask(config=config) 

152 butler, quantum, input = self._prepareQuantum(task) 

153 

154 with unittest.mock.patch.object( 

155 lsst.pipe.base.ButlerQuantumContext, "put") as put: 

156 testUtils.runTestQuantum(task, butler, quantum, mockRun=False) 

157 # Should not attempt to write nonexistent data 

158 put.assert_not_called() 

159 

160 

161# Hack around unittest's hacky test setup system 

162del ApdbMetricTestCase 

163 

164 

165class MemoryTester(lsst.utils.tests.MemoryTestCase): 

166 pass 

167 

168 

169def setup_module(module): 

170 lsst.utils.tests.init() 

171 

172 

173if __name__ == "__main__": 173 ↛ 174line 173 didn't jump to line 174, because the condition on line 173 was never true

174 lsst.utils.tests.init() 

175 unittest.main()