Coverage for tests/test_simple.py: 16%
83 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-14 01:56 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-02-14 01:56 -0800
1# This file is part of felis.
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
23import unittest
24from collections.abc import Iterable, MutableMapping, Sequence
25from typing import Any
27import yaml
29from felis import DEFAULT_FRAME, types
30from felis.simple import ForeignKeyConstraint, SimpleVisitor, UniqueConstraint
32TESTDIR = os.path.abspath(os.path.dirname(__file__))
33TEST_YAML = os.path.join(TESTDIR, "data", "test.yml")
36def _names(items: Iterable) -> Sequence[str]:
37 """Return names of items."""
38 return [item.name for item in items]
41class VisitorTestCase(unittest.TestCase):
42 """Tests for both SimpleVisitor classes."""
44 schema_obj: MutableMapping[str, Any] = {}
46 def setUp(self) -> None:
47 """Load data from test file."""
48 with open(TEST_YAML) as test_yaml:
49 self.schema_obj = yaml.load(test_yaml, Loader=yaml.SafeLoader)
50 self.schema_obj.update(DEFAULT_FRAME)
52 def test_schema(self) -> None:
53 """Check schema generated by SimpleVisitor class"""
54 visitor = SimpleVisitor()
55 schema = visitor.visit_schema(self.schema_obj)
57 self.assertIsNotNone(schema)
58 self.assertEqual(schema.name, "sdqa")
59 self.assertIsNotNone(schema.tables)
61 table_names = [
62 "sdqa_ImageStatus",
63 "sdqa_Metric",
64 "sdqa_Rating_ForAmpVisit",
65 "sdqa_Rating_CcdVisit",
66 "sdqa_Threshold",
67 ]
69 # Check schema.tables attribute.
70 self.assertCountEqual(set(_names(schema.tables)), set(table_names))
72 tables = {table.name: table for table in schema.tables}
74 # Details of sdqa_ImageStatus table.
75 table = tables["sdqa_ImageStatus"]
76 self.assertEqual(_names(table.columns), ["sdqa_imageStatusId", "statusName", "definition"])
77 self.assertEqual(
78 [column.datatype for column in table.columns], [types.Short, types.String, types.String]
79 )
80 self.assertEqual([column.length for column in table.columns], [None, 30, 255])
81 self.assertEqual(
82 [column.annotations for column in table.columns],
83 [
84 {"mysql:datatype": "SMALLINT"},
85 {"mysql:datatype": "VARCHAR(30)"},
86 {"mysql:datatype": "VARCHAR(255)"},
87 ],
88 )
89 self.assertEqual(_names(table.primary_key), ["sdqa_imageStatusId"])
90 self.assertFalse(table.indexes)
91 self.assertEqual(table.annotations, {"mysql:engine": "MyISAM"})
93 # Details of sdqa_Metric table.
94 table = tables["sdqa_Metric"]
95 self.assertEqual(
96 _names(table.columns), ["sdqa_metricId", "metricName", "physicalUnits", "dataType", "definition"]
97 )
98 self.assertEqual(
99 [column.datatype for column in table.columns],
100 [types.Short, types.String, types.String, types.Char, types.String],
101 )
102 self.assertEqual([column.length for column in table.columns], [None, 30, 30, 1, 255])
103 self.assertEqual(_names(table.primary_key), ["sdqa_metricId"])
104 self.assertFalse(table.indexes)
105 self.assertEqual(table.annotations, {"mysql:engine": "MyISAM"})
107 # It defines a unique constraint.
108 self.assertEqual(len(table.constraints), 1)
109 constraint = table.constraints[0]
110 self.assertIsInstance(constraint, UniqueConstraint)
111 assert isinstance(constraint, UniqueConstraint) # for mypy
112 self.assertEqual(constraint.name, "UQ_sdqaMetric_metricName")
113 self.assertEqual(_names(constraint.columns), ["metricName"])
114 self.assertEqual(constraint.annotations, {})
116 # Details of sdqa_Rating_ForAmpVisit table.
117 table = tables["sdqa_Rating_ForAmpVisit"]
118 self.assertEqual(
119 _names(table.columns),
120 [
121 "sdqa_ratingId",
122 "sdqa_metricId",
123 "sdqa_thresholdId",
124 "ampVisitId",
125 "metricValue",
126 "metricSigma",
127 ],
128 )
129 self.assertEqual(_names(table.primary_key), ["sdqa_ratingId"])
130 self.assertEqual(
131 [column.datatype for column in table.columns],
132 [types.Long, types.Short, types.Short, types.Long, types.Double, types.Double],
133 )
134 self.assertEqual(table.annotations, {"mysql:engine": "MyISAM"})
136 # constraints
137 self.assertEqual(len(table.constraints), 2)
138 constraint = table.constraints[0]
139 self.assertIsInstance(constraint, UniqueConstraint)
140 assert isinstance(constraint, UniqueConstraint) # for mypy
141 self.assertEqual(constraint.name, "UQ_sdqaRatingForAmpVisit_metricId_ampVisitId")
142 self.assertEqual(_names(constraint.columns), ["sdqa_metricId", "ampVisitId"])
143 self.assertEqual(constraint.annotations, {})
144 constraint = table.constraints[1]
145 self.assertIsInstance(constraint, ForeignKeyConstraint)
146 assert isinstance(constraint, ForeignKeyConstraint) # for mypy
147 self.assertEqual(constraint.name, "FK_sdqa_Rating_ForAmpVisit_sdqa_Metric")
148 self.assertEqual(_names(constraint.columns), ["sdqa_metricId"])
149 self.assertEqual(_names(constraint.referenced_columns), ["sdqa_metricId"])
150 self.assertIs(constraint.referenced_columns[0].table, tables["sdqa_Metric"])
151 self.assertEqual(constraint.annotations, {})
153 # It has a bunch of indices.
154 self.assertEqual(len(table.indexes), 3)
155 index = table.indexes[0]
156 self.assertEqual(index.name, "IDX_sdqaRatingForAmpVisit_metricId")
157 self.assertEqual(_names(index.columns), ["sdqa_metricId"])
158 self.assertEqual(index.annotations, {})
159 index = table.indexes[1]
160 self.assertEqual(index.name, "IDX_sdqaRatingForAmpVisit_thresholdId")
161 self.assertEqual(_names(index.columns), ["sdqa_thresholdId"])
162 self.assertEqual(index.annotations, {})
163 index = table.indexes[2]
164 self.assertEqual(index.name, "IDX_sdqaRatingForAmpVisit_ampVisitId")
165 self.assertEqual(_names(index.columns), ["ampVisitId"])
166 self.assertEqual(index.annotations, {})
169if __name__ == "__main__": 169 ↛ 170line 169 didn't jump to line 170, because the condition on line 169 was never true
170 unittest.main()