Skip to content

Commit f62feb8

Browse files
rzatsmelange396
andauthored
Refactor covid_hosp auto columns (#1203)
reworked common.Database to be more reflective/introspective w/ CovidHospSomething (YAML representation accessor), and more useful as an object instead of a class, and pulled appropriate methods into it that were previously in a "utils" file. greatly simplified other common.Xxx subclasses, and rearranged lots of tests. Co-authored-by: melange396 <[email protected]>
1 parent 925f88e commit f62feb8

34 files changed

+708
-1069
lines changed

integrations/acquisition/covid_hosp/facility/test_scenarios.py

+27-57
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
# standard library
44
import unittest
5-
from unittest.mock import MagicMock
5+
from unittest.mock import patch
66

77
# first party
8-
from delphi.epidata.acquisition.covid_hosp.common.database import Database
9-
from delphi.epidata.acquisition.covid_hosp.common.test_utils import UnitTestUtils
8+
from delphi.epidata.acquisition.covid_hosp.facility.database import Database
9+
from delphi.epidata.acquisition.covid_hosp.common.network import Network
10+
from delphi.epidata.acquisition.covid_hosp.common.test_utils import CovidHospTestCase, UnitTestUtils
1011
from delphi.epidata.client.delphi_epidata import Epidata
11-
from delphi.epidata.acquisition.covid_hosp.facility.update import Update
12-
import delphi.operations.secrets as secrets
12+
from delphi.epidata.common.covid_hosp.covid_hosp_schema_io import CovidHospSomething
1313

1414
# third party
1515
from freezegun import freeze_time
@@ -19,48 +19,26 @@
1919

2020
NEWLINE="\n"
2121

22-
class AcquisitionTests(unittest.TestCase):
22+
class AcquisitionTests(CovidHospTestCase):
2323

24-
def setUp(self):
25-
"""Perform per-test setup."""
26-
27-
# configure test data
28-
self.test_utils = UnitTestUtils(__file__)
29-
30-
# use the local instance of the Epidata API
31-
Epidata.BASE_URL = 'http://delphi_web_epidata/epidata/api.php'
32-
33-
# use the local instance of the epidata database
34-
secrets.db.host = 'delphi_database_epidata'
35-
secrets.db.epi = ('user', 'pass')
36-
37-
# clear relevant tables
38-
with Database.connect() as db:
39-
with db.new_cursor() as cur:
40-
cur.execute('truncate table covid_hosp_facility')
41-
cur.execute('truncate table covid_hosp_facility_key')
42-
cur.execute('truncate table covid_hosp_meta')
24+
db_class = Database
25+
test_util_context = __file__
4326

4427
@freeze_time("2021-03-16")
4528
def test_acquire_dataset(self):
4629
"""Acquire a new dataset."""
4730

48-
# only mock out network calls to external hosts
49-
mock_network = MagicMock()
50-
mock_network.fetch_metadata.return_value = \
51-
self.test_utils.load_sample_metadata()
52-
mock_network.fetch_dataset.return_value = \
53-
self.test_utils.load_sample_dataset()
54-
5531
# make sure the data does not yet exist
5632
with self.subTest(name='no data yet'):
5733
response = Epidata.covid_hosp_facility(
5834
'450822', Epidata.range(20200101, 20210101))
5935
self.assertEqual(response['result'], -2, response)
6036

6137
# acquire sample data into local database
62-
with self.subTest(name='first acquisition'):
63-
acquired = Update.run(network=mock_network)
38+
with self.subTest(name='first acquisition'), \
39+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()), \
40+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset()):
41+
acquired = Database().update_dataset()
6442
self.assertTrue(acquired)
6543

6644
# make sure the data now exists
@@ -89,12 +67,14 @@ def test_acquire_dataset(self):
8967
else:
9068
self.assertEqual(row[k], v, f"row[{k}] is {row[k]} not {v}")
9169

92-
# expect 113 fields per row (114 database columns, except `id`)
93-
self.assertEqual(len(row), 113)
70+
# Expect len(row) to equal the amount of dynamic columns + one extra issue column
71+
self.assertEqual(len(row), len(list(CovidHospSomething().columns('covid_hosp_facility'))) + 1)
9472

9573
# re-acquisition of the same dataset should be a no-op
96-
with self.subTest(name='second acquisition'):
97-
acquired = Update.run(network=mock_network)
74+
with self.subTest(name='second acquisition'), \
75+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()), \
76+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset()):
77+
acquired = Database().update_dataset()
9878
self.assertFalse(acquired)
9979

10080
# make sure the data still exists
@@ -108,16 +88,11 @@ def test_acquire_dataset(self):
10888
def test_facility_lookup(self):
10989
"""Lookup facilities using various filters."""
11090

111-
# only mock out network calls to external hosts
112-
mock_network = MagicMock()
113-
mock_network.fetch_metadata.return_value = \
114-
self.test_utils.load_sample_metadata()
115-
mock_network.fetch_dataset.return_value = \
116-
self.test_utils.load_sample_dataset()
117-
11891
# acquire sample data into local database
119-
with self.subTest(name='first acquisition'):
120-
acquired = Update.run(network=mock_network)
92+
with self.subTest(name='first acquisition'), \
93+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()), \
94+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset()):
95+
acquired = Database().update_dataset()
12196
self.assertTrue(acquired)
12297

12398
# texas ground truth, sorted by `hospital_pk`
@@ -181,16 +156,11 @@ def test_facility_lookup(self):
181156
response = Epidata.covid_hosp_facility_lookup(state='not a state')
182157
self.assertEqual(response['result'], -2)
183158

184-
# update facility info
185-
mock_network = MagicMock()
186-
mock_network.fetch_metadata.return_value = \
187-
self.test_utils.load_sample_metadata('metadata_update_facility.csv')
188-
mock_network.fetch_dataset.return_value = \
189-
self.test_utils.load_sample_dataset('dataset_update_facility.csv')
190-
191-
# acquire sample data into local database
192-
with self.subTest(name='second acquisition'):
193-
acquired = Update.run(network=mock_network)
159+
# acquire sample data into local database with updated facility info
160+
with self.subTest(name='second acquisition'), \
161+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata('metadata_update_facility.csv')), \
162+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset('dataset_update_facility.csv')):
163+
acquired = Database().update_dataset()
194164
self.assertTrue(acquired)
195165

196166
texas_hospitals[1]['zip'] = '88888'

integrations/acquisition/covid_hosp/state_daily/test_scenarios.py

+18-41
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,20 @@
1111

1212
# first party
1313
from delphi.epidata.acquisition.covid_hosp.state_daily.database import Database
14-
from delphi.epidata.acquisition.covid_hosp.common.test_utils import UnitTestUtils
14+
from delphi.epidata.acquisition.covid_hosp.common.test_utils import CovidHospTestCase, UnitTestUtils
1515
from delphi.epidata.client.delphi_epidata import Epidata
16-
from delphi.epidata.acquisition.covid_hosp.state_daily.update import Update
17-
from delphi.epidata.acquisition.covid_hosp.state_daily.network import Network
18-
from delphi.epidata.acquisition.covid_hosp.common.utils import Utils
19-
import delphi.operations.secrets as secrets
16+
from delphi.epidata.acquisition.covid_hosp.common.network import Network
17+
from delphi.epidata.common.covid_hosp.covid_hosp_schema_io import CovidHospSomething
2018

2119
# py3tester coverage target (equivalent to `import *`)
2220
__test_target__ = \
2321
'delphi.epidata.acquisition.covid_hosp.state_daily.update'
2422

2523

26-
class AcquisitionTests(unittest.TestCase):
24+
class AcquisitionTests(CovidHospTestCase):
2725

28-
def setUp(self):
29-
"""Perform per-test setup."""
30-
31-
# configure test data
32-
self.test_utils = UnitTestUtils(__file__)
33-
34-
# use the local instance of the Epidata API
35-
Epidata.BASE_URL = 'http://delphi_web_epidata/epidata/api.php'
36-
37-
# use the local instance of the epidata database
38-
secrets.db.host = 'delphi_database_epidata'
39-
secrets.db.epi = ('user', 'pass')
40-
41-
# clear relevant tables
42-
with Database.connect() as db:
43-
with db.new_cursor() as cur:
44-
cur.execute('truncate table covid_hosp_state_daily')
45-
cur.execute('truncate table covid_hosp_state_timeseries')
46-
cur.execute('truncate table covid_hosp_meta')
26+
db_class = Database
27+
test_util_context = __file__
4728

4829
@freeze_time("2021-03-16")
4930
def test_acquire_dataset(self):
@@ -61,8 +42,8 @@ def test_acquire_dataset(self):
6142
patch.object(Network, 'fetch_dataset', side_effect=[self.test_utils.load_sample_dataset("dataset0.csv"), # dataset for 3/13
6243
self.test_utils.load_sample_dataset("dataset0.csv"), # first dataset for 3/15
6344
self.test_utils.load_sample_dataset()] # second dataset for 3/15
64-
) as mock_fetch:
65-
acquired = Update.run()
45+
):
46+
acquired = Database().update_dataset()
6647
self.assertTrue(acquired)
6748
self.assertEqual(mock_fetch_meta.call_count, 1)
6849

@@ -82,18 +63,18 @@ def test_acquire_dataset(self):
8263
self.assertAlmostEqual(actual, expected)
8364
self.assertIsNone(row['critical_staffing_shortage_today_no'])
8465

85-
# expect 61 fields per row (62 database columns, except `id`) # TODO: ??? this is wrong!
86-
self.assertEqual(len(row), 118)
66+
# Expect len(row) to equal the amount of dynamic columns + one extra issue column
67+
self.assertEqual(len(row), len(list(CovidHospSomething().columns('state_daily'))) + 1)
8768

8869
with self.subTest(name='all date batches acquired'):
8970
response = Epidata.covid_hosp('WY', Epidata.range(20200101, 20210101), issues=20210313)
9071
self.assertEqual(response['result'], 1)
9172

9273
# re-acquisition of the same dataset should be a no-op
9374
with self.subTest(name='second acquisition'), \
94-
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()) as mock_fetch_meta, \
95-
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset()) as mock_fetch:
96-
acquired = Update.run()
75+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()), \
76+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset()):
77+
acquired = Database().update_dataset()
9778
self.assertFalse(acquired)
9879

9980
# make sure the data still exists
@@ -114,18 +95,14 @@ def test_acquire_specific_issue(self):
11495

11596
# acquire sample data into local database
11697
# mock out network calls to external hosts
117-
with Database.connect() as db:
98+
with Database().connect() as db:
11899
pre_max_issue = db.get_max_issue()
119100
self.assertEqual(pre_max_issue, pd.Timestamp('1900-01-01 00:00:00'))
120101
with self.subTest(name='first acquisition'), \
121-
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()) as mock_fetch_meta, \
122-
patch.object(Network, 'fetch_dataset', side_effect=[self.test_utils.load_sample_dataset("dataset0.csv")]
123-
) as mock_fetch:
124-
acquired = Utils.update_dataset(Database,
125-
Network,
126-
date(2021, 3, 12),
127-
date(2021, 3, 14))
128-
with Database.connect() as db:
102+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()), \
103+
patch.object(Network, 'fetch_dataset', side_effect=[self.test_utils.load_sample_dataset("dataset0.csv")]):
104+
acquired = Database().update_dataset(date(2021, 3, 12), date(2021, 3, 14))
105+
with Database().connect() as db:
129106
post_max_issue = db.get_max_issue()
130107
self.assertEqual(post_max_issue, pd.Timestamp('2021-03-13 00:00:00'))
131108
self.assertTrue(acquired)

integrations/acquisition/covid_hosp/state_timeseries/test_scenarios.py

+25-43
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
# standard library
44
import unittest
55
from unittest.mock import MagicMock
6+
from unittest.mock import patch
67

78
# first party
8-
from delphi.epidata.acquisition.covid_hosp.common.database import Database
9-
from delphi.epidata.acquisition.covid_hosp.common.test_utils import UnitTestUtils
9+
from delphi.epidata.acquisition.covid_hosp.state_timeseries.database import Database
10+
from delphi.epidata.acquisition.covid_hosp.common.network import Network
11+
from delphi.epidata.acquisition.covid_hosp.common.test_utils import CovidHospTestCase, UnitTestUtils
1012
from delphi.epidata.client.delphi_epidata import Epidata
11-
from delphi.epidata.acquisition.covid_hosp.state_timeseries.update import Update
12-
import delphi.operations.secrets as secrets
13+
from delphi.epidata.common.covid_hosp.covid_hosp_schema_io import CovidHospSomething
1314

1415
# third party
1516
from freezegun import freeze_time
@@ -19,47 +20,28 @@
1920
'delphi.epidata.acquisition.covid_hosp.state_timeseries.update'
2021

2122

22-
class AcquisitionTests(unittest.TestCase):
23+
class AcquisitionTests(CovidHospTestCase):
2324

24-
def setUp(self):
25-
"""Perform per-test setup."""
26-
27-
# configure test data
28-
self.test_utils = UnitTestUtils(__file__)
29-
30-
# use the local instance of the Epidata API
31-
Epidata.BASE_URL = 'http://delphi_web_epidata/epidata/api.php'
32-
33-
# use the local instance of the epidata database
34-
secrets.db.host = 'delphi_database_epidata'
35-
secrets.db.epi = ('user', 'pass')
36-
37-
# clear relevant tables
38-
with Database.connect() as db:
39-
with db.new_cursor() as cur:
40-
cur.execute('truncate table covid_hosp_state_daily')
41-
cur.execute('truncate table covid_hosp_state_timeseries')
42-
cur.execute('truncate table covid_hosp_meta')
25+
db_class = Database
26+
test_util_context = __file__
27+
# TODO: no need for the following after covid_hosp table split is merged
28+
# (in https://github.com/cmu-delphi/delphi-epidata/pull/1126)
29+
extra_tables_used = ['covid_hosp_state_daily']
4330

4431
@freeze_time("2021-03-17")
4532
def test_acquire_dataset(self):
4633
"""Acquire a new dataset."""
4734

48-
# only mock out network calls to external hosts
49-
mock_network = MagicMock()
50-
mock_network.fetch_metadata.return_value = \
51-
self.test_utils.load_sample_metadata()
52-
mock_network.fetch_dataset.return_value = \
53-
self.test_utils.load_sample_dataset()
54-
5535
# make sure the data does not yet exist
5636
with self.subTest(name='no data yet'):
5737
response = Epidata.covid_hosp('MA', Epidata.range(20200101, 20210101))
5838
self.assertEqual(response['result'], -2)
5939

6040
# acquire sample data into local database
61-
with self.subTest(name='first acquisition'):
62-
acquired = Update.run(network=mock_network)
41+
with self.subTest(name='first acquisition'), \
42+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()), \
43+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset()):
44+
acquired = Database().update_dataset()
6345
self.assertTrue(acquired)
6446

6547
# make sure the data now exists
@@ -78,12 +60,14 @@ def test_acquire_dataset(self):
7860
self.assertAlmostEqual(actual, expected)
7961
self.assertIsNone(row['critical_staffing_shortage_today_no'])
8062

81-
# expect 61 fields per row (62 database columns, except `id`) # TODO: ??? this is wrong!
82-
self.assertEqual(len(row), 118)
63+
# Expect len(row) to equal the amount of dynamic columns + one extra issue column
64+
self.assertEqual(len(row), len(list(CovidHospSomething().columns('state_timeseries'))) + 1)
8365

8466
# re-acquisition of the same dataset should be a no-op
85-
with self.subTest(name='second acquisition'):
86-
acquired = Update.run(network=mock_network)
67+
with self.subTest(name='second acquisition'), \
68+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata()), \
69+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset()):
70+
acquired = Database().update_dataset()
8771
self.assertFalse(acquired)
8872

8973
# make sure the data still exists
@@ -93,13 +77,11 @@ def test_acquire_dataset(self):
9377
self.assertEqual(len(response['epidata']), 1)
9478

9579
# acquire new data into local database
96-
with self.subTest(name='first acquisition'):
80+
with self.subTest(name='updated acquisition'), \
81+
patch.object(Network, 'fetch_metadata', return_value=self.test_utils.load_sample_metadata("metadata2.csv")), \
82+
patch.object(Network, 'fetch_dataset', return_value=self.test_utils.load_sample_dataset("dataset2.csv")):
9783
# acquire new data with 3/16 issue date
98-
mock_network.fetch_metadata.return_value = \
99-
self.test_utils.load_sample_metadata("metadata2.csv")
100-
mock_network.fetch_dataset.return_value = \
101-
self.test_utils.load_sample_dataset("dataset2.csv")
102-
acquired = Update.run(network=mock_network)
84+
acquired = Database().update_dataset()
10385
self.assertTrue(acquired)
10486

10587
with self.subTest(name='as_of checks'):

0 commit comments

Comments
 (0)