blob: 583dbe1ea154d38a3b4dcb7d1c6f652f5c3e694a [file] [log] [blame]
Anthonios Partheniouaff037a2021-04-21 11:00:09 -04001# Copyright 2021 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""ChangeSummary tests."""
16
17__author__ = "partheniou@google.com (Anthonios Partheniou)"
18
19import pathlib
20import shutil
21import unittest
22
23import pandas as pd
24
25from changesummary import ChangeSummary
26from changesummary import ChangeType
27from changesummary import DirectoryDoesNotExist
28
29SCRIPTS_DIR = pathlib.Path(__file__).parent.resolve()
30NEW_ARTIFACTS_DIR = SCRIPTS_DIR / "test_resources" / "new_artifacts_dir"
31CURRENT_ARTIFACTS_DIR = SCRIPTS_DIR / "test_resources" / "current_artifacts_dir"
32TEMP_DIR = SCRIPTS_DIR / "test_resources" / "temp"
33
34
35class TestChangeSummary(unittest.TestCase):
36 def setUp(self):
37 # Clear temporary directory
38 shutil.rmtree(TEMP_DIR, ignore_errors=True)
39 # Create temporary directory
40 pathlib.Path(TEMP_DIR).mkdir()
41
42 self.cs = ChangeSummary(NEW_ARTIFACTS_DIR, CURRENT_ARTIFACTS_DIR, TEMP_DIR, [])
43
44 def test_raises_on_directory_not_found_new_artifacts_dir(self):
45 with self.assertRaises(DirectoryDoesNotExist):
46 ChangeSummary(
47 "invalid_artifact_dir", CURRENT_ARTIFACTS_DIR, TEMP_DIR, []
48 ).detect_discovery_changes()
49
50 def test_raises_on_directory_not_found_current_artifacts_dir(self):
51 with self.assertRaises(DirectoryDoesNotExist):
52 ChangeSummary(
53 NEW_ARTIFACTS_DIR, "invalid_artifact_dir", TEMP_DIR, []
54 ).detect_discovery_changes()
55
56 def test_raises_on_directory_not_found_temp_dir(self):
57 # Remove temporary directory
58 shutil.rmtree(TEMP_DIR, ignore_errors=True)
59
60 with self.assertRaises(DirectoryDoesNotExist):
61 ChangeSummary(
62 NEW_ARTIFACTS_DIR, CURRENT_ARTIFACTS_DIR, "invalid_temp_dir", []
63 ).detect_discovery_changes()
64
65 # Create temporary directory
66 pathlib.Path(TEMP_DIR).mkdir()
67
68 ChangeSummary(
69 NEW_ARTIFACTS_DIR, CURRENT_ARTIFACTS_DIR, TEMP_DIR, []
70 ).detect_discovery_changes()
71
72 def test_raises_on_directory_not_found(self):
73 with self.assertRaises(DirectoryDoesNotExist):
74 self.cs._raise_if_directory_not_found(directory="invalid_dir")
75
76 def test_load_json_to_dataframe_returns_empty_df_if_file_path_invalid(self):
77 df = self.cs._load_json_to_dataframe(file_path="invalid_path")
78 self.assertTrue(df.empty)
79
80 def test_load_json_to_dataframe_returns_expected_data(self):
81 doc_path = NEW_ARTIFACTS_DIR / "drive.v3.json"
82 df = self.cs._load_json_to_dataframe(file_path=doc_path)
83 self.assertEqual(df["name"].iloc[0], "drive")
84 self.assertEqual(df["version"].iloc[0], "v3")
85
86 def test_get_discovery_differences_for_new_doc_returns_expected_dataframe(self):
87 df = self.cs._get_discovery_differences("drive.v3.json")
88 # Assume that `drive.v3.json` is a new discovery artifact that doesn't
89 # exist in `CURRENT_ARTIFACTS_DIR`.
90 self.assertEqual(df["Name"].iloc[0], "drive")
91 self.assertEqual(df["Version"].iloc[0], "v3")
92
93 # All rows in the dataframe should have `True` in the `Added` column
94 # and `False` in the `Deleted` column.
95 # pd.Dataframe().all() will return `True` if all elements are `True`.
96 self.assertTrue(df["Added"].all())
97 self.assertTrue((~df["Deleted"]).all())
98
99 # There should be 74 unique key differences
100 self.assertEqual(len(df), 74)
101
102 # Expected Result for key 'schemas.File'
103 # Key Added Deleted Name Version ChangeType Count
104 # schemas.File True False drive v3 2 168
105 self.assertTrue(df[df["Key"] == "schemas.File"].Added.iloc[0])
106 self.assertFalse(df[df["Key"] == "schemas.File"].Deleted.iloc[0])
107 self.assertEqual(
108 df[df["Key"] == "schemas.File"].ChangeType.iloc[0], ChangeType.ADDED
109 )
110 self.assertEqual(df[df["Key"] == "schemas.File"].Count.iloc[0], 168)
111
112 def test_get_discovery_differences_for_deleted_doc_returns_expected_dataframe(self):
113 df = self.cs._get_discovery_differences("cloudtasks.v2.json")
114 # Assuming that `cloudtasks.v2.json` is a discovery artifact that doesn't
115 # exist in `NEW_ARTIFACTS_DIR`.
116 self.assertEqual(df["Name"].iloc[0], "cloudtasks")
117 self.assertEqual(df["Version"].iloc[0], "v2")
118
119 # All rows in the dataframe should have `False` in the `Added` column
120 # and `True` in the `Deleted` column.
121 # pd.Dataframe().all() will return `True` if all elements are `True`.
122 self.assertTrue((~df["Added"]).all())
123 self.assertTrue(df["Deleted"].all())
124
125 # There should be 72 unique key differences
126 self.assertEqual(len(df), 72)
127
128 # Expected Result for key 'schemas.Task'
129 # Key Added Deleted Name Version ChangeType Count
130 # schemas.Task False True cloudtasks v2 1 18
131 self.assertFalse(df[df["Key"] == "schemas.Task"].Added.iloc[0])
132 self.assertTrue(df[df["Key"] == "schemas.Task"].Deleted.iloc[0])
133 self.assertEqual(
134 df[df["Key"] == "schemas.Task"].ChangeType.iloc[0], ChangeType.DELETED
135 )
136 self.assertEqual(df[df["Key"] == "schemas.Task"].Count.iloc[0], 18)
137
138 def test_get_discovery_differences_for_changed_doc_returns_expected_dataframe(self):
139 # Assuming that `bigquery.v2.json` is a discovery artifact has
140 # changed. There will be a mix of keys being added, changed or deleted.
141 df = self.cs._get_discovery_differences("bigquery.v2.json")
142
143 self.assertEqual(df["Name"].iloc[0], "bigquery")
144 self.assertEqual(df["Version"].iloc[0], "v2")
145
146 # There should be 28 unique key differences
147 # 11 unique keys changed, 13 unique keys added, 4 unique keys deleted
148 self.assertEqual(len(df), 28)
149 self.assertEqual(len(df[df["ChangeType"] == ChangeType.CHANGED]), 11)
150 self.assertEqual(len(df[df["ChangeType"] == ChangeType.ADDED]), 13)
151 self.assertEqual(len(df[df["ChangeType"] == ChangeType.DELETED]), 4)
152
153 # Expected Result for key 'schemas.PrincipalComponentInfo'
154 # Key Added Deleted Name Version ChangeType Count
155 # schemas.PrincipalComponentInfo False True bigquery v2 1 10
156 key = "schemas.PrincipalComponentInfo"
157 self.assertFalse(df[df["Key"] == key].Added.iloc[0])
158 self.assertTrue(df[df["Key"] == key].Deleted.iloc[0])
159 self.assertEqual(df[df["Key"] == key].ChangeType.iloc[0], ChangeType.DELETED)
160 self.assertEqual(df[df["Key"] == key].Count.iloc[0], 10)
161
162 def test_build_summary_message_returns_expected_result(self):
163 msg = self.cs._build_summary_message(api_name="bigquery", is_feature=True)
164 self.assertEqual(msg, "feat(bigquery): update the api")
165 msg = self.cs._build_summary_message(api_name="bigquery", is_feature=False)
166 self.assertEqual(msg, "fix(bigquery): update the api")
167
168 def test_get_stable_versions(self):
169 # These versions should be considered stable
170 s = pd.Series(["v1", "v1.4", "v1.4.5"])
171 self.assertTrue(self.cs._get_stable_versions(s).all().iloc[0])
172
173 # These versions should not be considered stable
174 s = pd.Series(["v1b1", "v1alpha", "v1beta1"])
175 self.assertTrue((~self.cs._get_stable_versions(s)).all().iloc[0])
176
177 def test_detect_discovery_changes(self):
178 files_changed = ["bigquery.v2.json", "cloudtasks.v2.json", "drive.v3.json"]
179 cs = ChangeSummary(
180 NEW_ARTIFACTS_DIR, CURRENT_ARTIFACTS_DIR, TEMP_DIR, files_changed
181 )
182 cs.detect_discovery_changes()
183 print("test")
184 result = pd.read_csv(TEMP_DIR / "allapis.dataframe")
185
186 # bigquery was added
187 # 28 key changes in total.
188 # 11 unique keys changed, 13 unique keys added, 4 unique keys deleted
189 self.assertEqual(len(result[result["Name"] == "bigquery"]), 28)
190 self.assertEqual(
191 len(result[(result["Name"] == "bigquery") & result["Added"]]), 13
192 )
193 self.assertEqual(
194 len(result[(result["Name"] == "bigquery") & result["Deleted"]]), 4
195 )
196 self.assertTrue(result[result["Name"] == "bigquery"].IsStable.all())
197 self.assertTrue(result[result["Name"] == "bigquery"].IsFeatureAggregate.all())
198 self.assertEqual(
199 result[result["Name"] == "bigquery"].Summary.iloc[0],
200 "feat(bigquery): update the api",
201 )
202
203 # cloudtasks was deleted
204 # 72 key changes in total. All 72 key changes should be deletions.
205 self.assertEqual(len(result[result["Name"] == "cloudtasks"]), 72)
206 self.assertEqual(
207 len(result[(result["Name"] == "cloudtasks") & result["Added"]]), 0
208 )
209 self.assertEqual(
210 len(result[(result["Name"] == "cloudtasks") & result["Deleted"]]), 72
211 )
212 self.assertTrue(result[(result["Name"] == "cloudtasks")].IsStable.all())
213 self.assertTrue(
214 result[(result["Name"] == "cloudtasks")].IsFeatureAggregate.all()
215 )
216 self.assertEqual(
217 result[(result["Name"] == "cloudtasks")].Summary.iloc[0],
218 "feat(cloudtasks): update the api",
219 )
220
221 # drive was updated
222 # 74 key changes in total. All 74 key changes should be additions
223 self.assertEqual(len(result[result["Name"] == "drive"]), 74)
224 self.assertEqual(
225 len(result[(result["Name"] == "drive") & result["Added"]]), 74
226 )
227 self.assertEqual(
228 len(result[(result["Name"] == "drive") & result["Deleted"]]), 0
229 )
230 self.assertTrue(result[(result["Name"] == "drive")].IsStable.all())
231 self.assertTrue(
232 result[(result["Name"] == "drive")].IsFeatureAggregate.all()
233 )
234 self.assertEqual(
235 result[(result["Name"] == "drive")].Summary.iloc[0],
236 "feat(drive): update the api",
237 )
238
239if __name__ == "__main__":
240 unittest.main()