Coverage for python/lsst/verify/gen2tasks/testUtils.py: 46%

36 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-07-27 09:57 +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# 

23 

24__all__ = ["MetricTaskTestCase"] 

25 

26import abc 

27import unittest.mock 

28import inspect 

29 

30import lsst.utils.tests 

31 

32from lsst.pipe.base import Struct 

33from lsst.verify import Measurement 

34 

35 

36class MetricTaskTestCase(lsst.utils.tests.TestCase, metaclass=abc.ABCMeta): 

37 """Unit test base class for tests of `tasks.MetricTask`. 

38 

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. 

48 

49 This overridable method will be called during test setup. 

50 

51 Returns 

52 ------- 

53 task : `lsst.verify.tasks.MetricTask` 

54 A new MetricTask object to test. 

55 """ 

56 

57 task = None 

58 """The ``MetricTask`` being tested by this object 

59 (`tasks.MetricTask`). 

60 

61 This attribute is initialized automatically. 

62 """ 

63 

64 taskClass = None 

65 """The type of `task` (`tasks.MetricTask`-type). 

66 

67 This attribute is initialized automatically. 

68 """ 

69 

70 def setUp(self): 

71 """Setup common to all MetricTask tests. 

72 

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) 

80 

81 # Implementation classes will override run. Can't implement most tests if 

82 # it's mocked, risk excessive runtime if it isn't. 

83 

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} 

90 

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

97 

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 

103 

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) 

111 

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)