Coverage for tests/test_driver.py: 42%
82 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 13:12 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 13:12 +0000
1#
2# This file is part of ap_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#
24import functools
25import os
26import shutil
27import tempfile
28import unittest.mock
30import lsst.utils.tests
31from lsst.obs.base import RawIngestTask, DefineVisitsTask
32from lsst.ap.verify import pipeline_driver
33from lsst.ap.verify.testUtils import DataTestCase
34from lsst.ap.verify import Dataset, WorkspaceGen3
37TESTDIR = os.path.abspath(os.path.dirname(__file__))
40def _getDataIds(butler):
41 return list(butler.registry.queryDataIds({"instrument", "visit", "detector"}, datasets="raw"))
44def patchApPipeGen3(method):
45 """Shortcut decorator for consistently patching AP code.
46 """
47 @functools.wraps(method)
48 def wrapper(self, *args, **kwargs):
49 dbPatcher = unittest.mock.patch("lsst.ap.verify.pipeline_driver._makeApdb")
50 patchedMethod = dbPatcher(method)
51 return patchedMethod(self, *args, **kwargs)
52 return wrapper
55class PipelineDriverTestSuiteGen3(DataTestCase):
57 @classmethod
58 def setUpClass(cls):
59 super().setUpClass()
61 cls.dataset = Dataset(cls.testDataset)
63 def setUp(self):
64 super().setUp()
66 self._testDir = tempfile.mkdtemp()
67 self.addCleanup(shutil.rmtree, self._testDir, ignore_errors=True)
69 self.workspace = WorkspaceGen3(self._testDir)
70 self.dataset.makeCompatibleRepoGen3(self.workspace.repo)
71 raws = [os.path.join(self.dataset.rawLocation, "lsst_a_204595_R11_S01_i.fits")]
72 rawIngest = RawIngestTask(butler=self.workspace.workButler, config=RawIngestTask.ConfigClass())
73 rawIngest.run(raws, run=None)
74 defineVisit = DefineVisitsTask(butler=self.workspace.workButler,
75 config=DefineVisitsTask.ConfigClass())
76 defineVisit.run(self.workspace.workButler.registry.queryDataIds("exposure", datasets="raw"))
77 ids = _getDataIds(self.workspace.workButler)
78 self.apPipeArgs = pipeline_driver.ApPipeParser().parse_args(
79 ["--data-query", f"instrument = '{ids[0]['instrument']}' AND visit = {ids[0]['visit']}",
80 "--pipeline", os.path.join(TESTDIR, "MockApPipe.yaml")])
82 def testrunApPipeGen3Steps(self):
83 """Test that runApPipeGen3 runs the entire pipeline.
84 """
85 pipeline_driver.runApPipeGen3(self.workspace, self.apPipeArgs)
87 # Use datasets as a proxy for pipeline completion
88 id = _getDataIds(self.workspace.analysisButler)[0]
89 self.assertTrue(self.workspace.analysisButler.exists("calexp", id))
90 self.assertTrue(self.workspace.analysisButler.exists("src", id))
91 self.assertTrue(self.workspace.analysisButler.exists("goodSeeingDiff_differenceExp", id))
92 self.assertTrue(self.workspace.analysisButler.exists("goodSeeingDiff_diaSrc", id))
93 self.assertTrue(self.workspace.analysisButler.exists("apdb_marker", id))
94 self.assertTrue(self.workspace.analysisButler.exists("goodSeeingDiff_assocDiaSrc", id))
96 def _getArgs(self, call_args):
97 if call_args.args:
98 return call_args.args[1]
99 elif "args" in call_args.kwargs:
100 return call_args.kwargs["args"]
101 else:
102 self.fail(f"No APDB args passed to {call_args}!")
104 @patchApPipeGen3
105 def testrunApPipeGen3WorkspaceDb(self, mockDb):
106 """Test that runApPipeGen3 places a database in the workspace location by default.
107 """
108 pipeline_driver.runApPipeGen3(self.workspace, self.apPipeArgs)
110 mockDb.assert_called_once()
111 dbArgs = self._getArgs(mockDb.call_args)
112 self.assertIn("db_url", dbArgs)
113 self.assertEqual(dbArgs["db_url"], "sqlite:///" + self.workspace.dbLocation)
115 @patchApPipeGen3
116 def testrunApPipeGen3WorkspaceCustom(self, mockDb):
117 """Test that runApPipeGen3 places a database in the specified location.
118 """
119 self.apPipeArgs.db = "postgresql://somebody@pgdb.misc.org/custom_db"
120 pipeline_driver.runApPipeGen3(self.workspace, self.apPipeArgs)
122 mockDb.assert_called_once()
123 dbArgs = self._getArgs(mockDb.call_args)
124 self.assertIn("db_url", dbArgs)
125 self.assertEqual(dbArgs["db_url"], self.apPipeArgs.db)
127 def testrunApPipeGen3Reuse(self):
128 """Test that runApPipeGen3 does not run the pipeline at all (not even with
129 --skip-existing) if --skip-pipeline is provided.
130 """
131 skipArgs = pipeline_driver.ApPipeParser().parse_args(["--skip-pipeline"])
132 pipeline_driver.runApPipeGen3(self.workspace, skipArgs)
134 # Use datasets as a proxy for pipeline completion.
135 # Depending on the overall test setup, the dataset may or may not be
136 # registered if the pipeline didn't run; check both cases.
137 id = _getDataIds(self.workspace.analysisButler)[0]
138 calexpQuery = set(self.workspace.analysisButler.registry.queryDatasetTypes("calexp"))
139 calexpExists = len(calexpQuery) > 0
140 self.assertFalse(calexpExists and self.workspace.analysisButler.exists("calexp", id))
143class MemoryTester(lsst.utils.tests.MemoryTestCase):
144 pass
147def setup_module(module):
148 lsst.utils.tests.init()
151if __name__ == "__main__": 151 ↛ 152line 151 didn't jump to line 152, because the condition on line 151 was never true
152 lsst.utils.tests.init()
153 unittest.main()