Coverage for tests/test_jointcalRunner.py: 28%
83 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-17 02:57 -0700
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-17 02:57 -0700
1# This file is part of jointcal.
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 os.path
23import tempfile
24import unittest
25import unittest.mock
27import lsst.log
28import lsst.utils
30import lsst.daf.persistence
31import lsst.jointcal
32from lsst.meas.algorithms import DatasetConfig
33import lsst.pipe.base
35current_dir = os.path.abspath(os.path.dirname(__file__))
38# for MemoryTestCase
39def setup_module(module):
40 lsst.utils.tests.init()
43class TestJointcalRunner(lsst.utils.tests.TestCase):
44 """Test that JointcalRunner calls JointcalTask with appropriate arguments.
46 This test mocks a butler to force JointcalRunner to be called with
47 specific sets of parameters (e.g. 1 or 2 tracts), and mocks JointcalTask to
48 check that it is called the correct number of times (i.e. once per tract).
49 """
50 @classmethod
51 def setUpClass(cls):
52 cls.data_dir = os.path.join(current_dir, 'data')
54 def setUp(self):
55 def mock_get(arg):
56 """Return things that sub-tasks need from butler.get()."""
57 if arg == 'verify_job_filename':
58 return 'some/path/filename.job'
59 elif arg == 'ref_cat_config':
60 result = unittest.mock.Mock(DatasetConfig)
61 result.indexer = DatasetConfig().indexer
62 return result
63 else:
64 return None
66 def mock_dataRef(datasetType, level=None, dataId=None):
67 """Return a fake dataRef that always exists."""
68 ref = lsst.daf.persistence.ButlerDataRef(None, dataId)
69 ref.datasetExists = lambda: True
70 return ref
72 def mock_subset(datasetType, dataId=None):
73 """Return a fake butler subset containing one dataRef."""
74 return [mock_dataRef(datasetType, dataId=dataId)]
76 butlerPatcher = unittest.mock.patch("lsst.daf.persistence.Butler", autospec=True)
77 self.butler = butlerPatcher.start()
78 self.addCleanup(butlerPatcher.stop)
79 self.butler.return_value.get = mock_get
80 self.butler.return_value.subset = mock_subset
81 self.butler.return_value.dataRef = mock_dataRef
82 self.butler.return_value.getKeys.return_value = {'visit': int, 'ccd': int}
83 # static methods: mock on the class, not the return_value
84 self.butler.getMapperClass.return_value.getPackageName.return_value = 'jointcal'
85 self.butler.getMapperClass.return_value.getCameraName.return_value = 'cfht'
87 def prep_jointcal(self, tracts=None):
88 """Prepare a jointcal mock to be called by JointcalRunner.
90 We use the `tests/data/cfht_minimal` repo to provide a "real" refcat,
91 and use dataIds associated with it, even though we mock the butler.
93 Parameters
94 ----------
95 tracts : `list` [`int`]
96 List of tracts to build DataRefs for.
97 """
98 configfile = os.path.join(current_dir, 'config/config.py')
100 input_dir = os.path.join(self.data_dir, 'cfht_minimal')
101 output_dir = tempfile.mkdtemp() # we don't care about any outputs
103 visits = '849375^850587'
104 args = [input_dir, '--output', output_dir, '--doraise', '--configfile=%s'%configfile,
105 '--id', 'visit=%s'%visits, 'ccd=12']
106 if tracts is not None:
107 args.append('tract=%s'%'^'.join(str(tract) for tract in tracts))
109 config = lsst.jointcal.JointcalConfig()
110 parser = lsst.jointcal.JointcalTask._makeArgumentParser()
111 parsedArgs = parser.parse_args(config, args=args)
113 jointcalPatcher = unittest.mock.patch("lsst.jointcal.JointcalTask", autospec=True)
114 JointcalTask = jointcalPatcher.start()
115 self.addCleanup(jointcalPatcher.stop)
116 self.return_value = 100
117 result = lsst.pipe.base.Struct(exitStatus=self.return_value, job=unittest.mock.Mock())
118 JointcalTask.return_value.runDataRef.return_value = result
119 JointcalTask.return_value.log = unittest.mock.Mock() # jointcal.log is created in __init__
121 return parsedArgs, JointcalTask
123 def testJointcalRunnerOneTract(self):
124 parsedArgs, JointcalTask = self.prep_jointcal(tracts=[5])
125 runner = lsst.jointcal.JointcalRunner(JointcalTask, parsedArgs)
126 result = runner.run(parsedArgs)
127 self.assertEqual(result[0].exitStatus, self.return_value)
128 JointcalTask.return_value.runDataRef.assert_called_once()
130 def testJointcalRunnerTwoTracts(self):
131 parsedArgs, JointcalTask = self.prep_jointcal(tracts=[5, 6])
132 runner = lsst.jointcal.JointcalRunner(JointcalTask, parsedArgs)
133 result = runner.run(parsedArgs)
134 self.assertEqual(result[0].exitStatus, self.return_value)
135 self.assertEqual(JointcalTask.return_value.runDataRef.call_count, 2)
137 def testJointcalRunnerThreeTracts(self):
138 parsedArgs, JointcalTask = self.prep_jointcal(tracts=[5, 6, 7])
139 runner = lsst.jointcal.JointcalRunner(JointcalTask, parsedArgs)
140 result = runner.run(parsedArgs)
141 self.assertEqual(result[0].exitStatus, self.return_value)
142 self.assertEqual(JointcalTask.return_value.runDataRef.call_count, 3)
145class MemoryTester(lsst.utils.tests.MemoryTestCase):
146 pass
149if __name__ == "__main__": 149 ↛ 150line 149 didn't jump to line 150, because the condition on line 149 was never true
150 lsst.utils.tests.init()
151 unittest.main()