2
2
3
3
# standard library
4
4
import unittest
5
- from unittest .mock import MagicMock
6
- from unittest .mock import sentinel
5
+ from unittest .mock import (MagicMock , sentinel , patch )
7
6
8
- from delphi .epidata .acquisition .flusurv .flusurv import fetch_json
7
+ import delphi .epidata .acquisition .flusurv .flusurv as flusurv
9
8
10
9
# py3tester coverage target
11
10
__test_target__ = "delphi.epidata.acquisition.flusurv.flusurv"
12
11
13
12
13
+ # Example location-specific return JSON from CDC GRASP API. Contains
14
+ # partial data for "network_all" location and season 49.
15
+ network_all_example_data = {
16
+ 'default_data' : [
17
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 1 , 'rate' : 20.7 , 'weeklyrate' : 0.0 , 'mmwrid' : 2519 },
18
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 2 , 'rate' : 41.3 , 'weeklyrate' : 0.1 , 'mmwrid' : 2519 },
19
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 1 , 'sexid' : 0 , 'raceid' : 0 , 'rate' : 42 , 'weeklyrate' : 0.5 , 'mmwrid' : 2519 },
20
+
21
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 1 , 'rate' : 4.3 , 'weeklyrate' : 1.7 , 'mmwrid' : 2493 },
22
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 2 , 'rate' : 11.6 , 'weeklyrate' : 3.6 , 'mmwrid' : 2493 },
23
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 3 , 'rate' : 12.8 , 'weeklyrate' : 4.8 , 'mmwrid' : 2493 },
24
+
25
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 1 , 'rate' : 20.6 , 'weeklyrate' : 0.1 , 'mmwrid' : 2516 },
26
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 2 , 'rate' : 40.7 , 'weeklyrate' : 0.5 , 'mmwrid' : 2516 },
27
+
28
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 1 , 'rate' : 20.3 , 'weeklyrate' : 0.1 , 'mmwrid' : 2513 },
29
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 2 , 'rate' : 39.6 , 'weeklyrate' : 0.3 , 'mmwrid' : 2513 },
30
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 0 , 'sexid' : 0 , 'raceid' : 3 , 'rate' : 36.0 , 'weeklyrate' : 0.1 , 'mmwrid' : 2513 },
31
+ ]
32
+ }
33
+
34
+ # Example metadata response containing "master_lookup" element only, used
35
+ # for mapping between valueids and strata descriptions
36
+ master_lookup_metadata = {
37
+ 'master_lookup' : [
38
+ {'Variable' : 'Age' , 'valueid' : 1 , 'parentid' : 97 , 'Label' : '0-4 yr' , 'Color_HexValue' : '#d19833' , 'Enabled' : True },
39
+ {'Variable' : 'Age' , 'valueid' : 2 , 'parentid' : 97 , 'Label' : '5-17 yr' , 'Color_HexValue' : '#707070' , 'Enabled' : True },
40
+ {'Variable' : 'Age' , 'valueid' : 3 , 'parentid' : 98 , 'Label' : '18-49 yr' , 'Color_HexValue' : '#44b3c6' , 'Enabled' : True },
41
+ {'Variable' : 'Age' , 'valueid' : 4 , 'parentid' : 98 , 'Label' : '50-64 yr' , 'Color_HexValue' : '#516889' , 'Enabled' : True },
42
+ {'Variable' : 'Age' , 'valueid' : 5 , 'parentid' : 98 , 'Label' : '65+ yr' , 'Color_HexValue' : '#cc5e56' , 'Enabled' : True },
43
+ {'Variable' : 'Age' , 'valueid' : 7 , 'parentid' : 5 , 'Label' : '65-74 yr' , 'Color_HexValue' : '#cc5e56' , 'Enabled' : True },
44
+ {'Variable' : 'Age' , 'valueid' : 8 , 'parentid' : 5 , 'Label' : '75-84 yr' , 'Color_HexValue' : '#cc5e56' , 'Enabled' : True },
45
+ {'Variable' : 'Age' , 'valueid' : 9 , 'parentid' : 5 , 'Label' : '85+' , 'Color_HexValue' : '#cc5e56' , 'Enabled' : True },
46
+ {'Variable' : 'Age' , 'valueid' : 10 , 'parentid' : 3 , 'Label' : '18-29 yr' , 'Color_HexValue' : '#44b3c6' , 'Enabled' : True },
47
+ {'Variable' : 'Age' , 'valueid' : 11 , 'parentid' : 3 , 'Label' : '30-39 yr' , 'Color_HexValue' : '#44b3c6' , 'Enabled' : True },
48
+ {'Variable' : 'Age' , 'valueid' : 12 , 'parentid' : 3 , 'Label' : '40-49 yr' , 'Color_HexValue' : '#44b3c6' , 'Enabled' : True },
49
+ {'Variable' : 'Age' , 'valueid' : 21 , 'parentid' : 2 , 'Label' : '5-11 yr' , 'Color_HexValue' : '#707070' , 'Enabled' : True },
50
+ {'Variable' : 'Age' , 'valueid' : 22 , 'parentid' : 2 , 'Label' : '12-17 yr' , 'Color_HexValue' : '#707070' , 'Enabled' : True },
51
+ {'Variable' : 'Age' , 'valueid' : 97 , 'parentid' : 0 , 'Label' : '< 18' , 'Color_HexValue' : '#000000' , 'Enabled' : True },
52
+ {'Variable' : 'Age' , 'valueid' : 98 , 'parentid' : 0 , 'Label' : '>= 18' , 'Color_HexValue' : '#000000' , 'Enabled' : True },
53
+
54
+ {'Variable' : 'Race' , 'valueid' : 1 , 'parentid' : None , 'Label' : 'White' , 'Color_HexValue' : '#516889' , 'Enabled' : True },
55
+ {'Variable' : 'Race' , 'valueid' : 2 , 'parentid' : None , 'Label' : 'Black' , 'Color_HexValue' : '#44b3c6' , 'Enabled' : True },
56
+ {'Variable' : 'Race' , 'valueid' : 3 , 'parentid' : None , 'Label' : 'Hispanic/Latino' , 'Color_HexValue' : '#d19833' , 'Enabled' : True },
57
+ {'Variable' : 'Race' , 'valueid' : 4 , 'parentid' : None , 'Label' : 'Asian/Pacific Islander' , 'Color_HexValue' : '#cc5e56' , 'Enabled' : True },
58
+ {'Variable' : 'Race' , 'valueid' : 5 , 'parentid' : None , 'Label' : 'American Indian/Alaska Native' , 'Color_HexValue' : '#007d8e' , 'Enabled' : True },
59
+
60
+ {'Variable' : 'Sex' , 'valueid' : 1 , 'parentid' : None , 'Label' : 'Male' , 'Color_HexValue' : '#44b3c6' , 'Enabled' : True },
61
+ {'Variable' : 'Sex' , 'valueid' : 2 , 'parentid' : None , 'Label' : 'Female' , 'Color_HexValue' : '#F2775F' , 'Enabled' : True },
62
+
63
+ {'Variable' : None , 'valueid' : 0 , 'parentid' : 0 , 'Label' : 'Overall' , 'Color_HexValue' : '#000000' , 'Enabled' : True },
64
+ ],
65
+ }
66
+
67
+ # Map derived from "master_lookup" dictionary above mapping between valueids
68
+ # by type and cleaned-up descriptions (no spaces or capital letters, etc)
69
+ id_label_map = {
70
+ "Age" : {
71
+ 1 : "0t4" ,
72
+ 2 : "5t17" ,
73
+ 3 : "18t49" ,
74
+ 4 : "50t64" ,
75
+ 5 : "65+" ,
76
+ 7 : "65t74" ,
77
+ 8 : "75t84" ,
78
+ 9 : "85+" ,
79
+ 10 : "18t29" ,
80
+ 11 : "30t39" ,
81
+ 12 : "40t49" ,
82
+ 21 : "5t11" ,
83
+ 22 : "12t17" ,
84
+ 97 : "<18" ,
85
+ 98 : ">=18" ,
86
+ },
87
+ "Race" : {
88
+ 1 : "white" ,
89
+ 2 : "black" ,
90
+ 3 : "hispaniclatino" ,
91
+ 4 : "asianpacificislander" ,
92
+ 5 : "americanindianalaskanative" ,
93
+ },
94
+ "Sex" : {
95
+ 1 : "male" ,
96
+ 2 : "female" ,
97
+ },
98
+ }
99
+
100
+
14
101
class FunctionTests (unittest .TestCase ):
15
102
"""Tests each function individually."""
16
103
@@ -28,6 +115,98 @@ def test_fetch_json(self):
28
115
requests_impl = MagicMock ()
29
116
requests_impl .get .return_value = response_object
30
117
31
- actual = fetch_json (path , payload , requests_impl = requests_impl )
118
+ actual = flusurv . fetch_json (path , payload , requests_impl = requests_impl )
32
119
33
120
self .assertEqual (actual , sentinel .expected )
121
+
122
+ def test_mmwrid_to_epiweek (self ):
123
+ # Test epoch
124
+ self .assertEqual (flusurv .mmwrid_to_epiweek (2179 ), 200340 )
125
+
126
+ metadata = flusurv .fetch_flusurv_metadata ()
127
+ for mmwr in metadata ["mmwr" ]:
128
+ self .assertEqual (flusurv .mmwrid_to_epiweek (mmwr ["mmwrid" ]), mmwr ["yearweek" ])
129
+
130
+ @patch (__test_target__ + ".fetch_flusurv_location" )
131
+ def test_get_data (self , MockFlusurvLocation ):
132
+ MockFlusurvLocation .return_value = network_all_example_data
133
+
134
+ self .assertEqual (flusurv .get_data ("network_all" , [30 , 49 ]), {
135
+ 201014 : {"rate_race_white" : 0.0 , "rate_race_black" : 0.1 , "rate_age_0" : 0.5 },
136
+ 200940 : {"rate_race_white" : 1.7 , "rate_race_black" : 3.6 , "rate_race_hispaniclatino" : 4.8 },
137
+ 201011 : {"rate_race_white" : 0.1 , "rate_race_black" : 0.5 },
138
+ 201008 : {"rate_race_white" : 0.1 , "rate_race_black" : 0.3 , "rate_race_hispaniclatino" : 0.1 },
139
+ }
140
+ )
141
+
142
+ @patch (__test_target__ + ".fetch_flusurv_metadata" )
143
+ def test_group_by_epiweek (self , MockFlusurvMetadata ):
144
+ # Flusurv metadata is fetched by `make_id_label_map()`.
145
+ MockFlusurvMetadata .return_value = master_lookup_metadata
146
+
147
+ input_data = network_all_example_data
148
+ self .assertEqual (flusurv .group_by_epiweek (input_data ), {
149
+ 201014 : {"rate_race_white" : 0.0 , "rate_race_black" : 0.1 , "rate_age_0" : 0.5 },
150
+ 200940 : {"rate_race_white" : 1.7 , "rate_race_black" : 3.6 , "rate_race_hispaniclatino" : 4.8 },
151
+ 201011 : {"rate_race_white" : 0.1 , "rate_race_black" : 0.5 },
152
+ 201008 : {"rate_race_white" : 0.1 , "rate_race_black" : 0.3 , "rate_race_hispaniclatino" : 0.1 },
153
+ }
154
+ )
155
+
156
+ duplicate_input_data = {
157
+ 'default_data' : [
158
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 1 , 'sexid' : 0 , 'raceid' : 0 , 'rate' : 42 , 'weeklyrate' : 0.5 , 'mmwrid' : 2519 },
159
+ {'networkid' : 1 , 'catchmentid' : 22 , 'seasonid' : 49 , 'ageid' : 1 , 'sexid' : 0 , 'raceid' : 0 , 'rate' : 42 , 'weeklyrate' : 54 , 'mmwrid' : 2519 },
160
+ ]
161
+ }
162
+
163
+ with self .assertWarnsRegex (Warning , "warning: Multiple rates seen for 201014" ):
164
+ flusurv .group_by_epiweek (duplicate_input_data )
165
+
166
+ with self .assertRaisesRegex (Exception , "no data found" ):
167
+ flusurv .group_by_epiweek ({"default_data" : []})
168
+
169
+ @patch ('builtins.print' )
170
+ def test_group_by_epiweek_print_msgs (self , mock_print ):
171
+ input_data = network_all_example_data
172
+ flusurv .group_by_epiweek (input_data )
173
+ mock_print .assert_called_with ("found data for 4 epiweeks" )
174
+
175
+ def test_get_current_issue (self ):
176
+ input_data = {
177
+ 'loaddatetime' : 'Sep 12, 2023'
178
+ }
179
+ self .assertEqual (flusurv .get_current_issue (input_data ), 202337 )
180
+
181
+ @patch (__test_target__ + ".fetch_flusurv_metadata" )
182
+ def test_make_id_label_map (self , MockFlusurvMetadata ):
183
+ MockFlusurvMetadata .return_value = master_lookup_metadata
184
+ self .assertEqual (flusurv .make_id_label_map (), id_label_map )
185
+
186
+ def test_groupids_to_name (self ):
187
+ ids = (
188
+ (1 , 0 , 0 ),
189
+ (9 , 0 , 0 ),
190
+ (0 , 2 , 0 ),
191
+ (0 , 0 , 3 ),
192
+ (0 , 0 , 5 ),
193
+ (0 , 0 , 0 ),
194
+ )
195
+ expected_list = [
196
+ "rate_age_0" ,
197
+ "rate_age_7" ,
198
+ "rate_sex_female" ,
199
+ "rate_race_hispaniclatino" ,
200
+ "rate_race_americanindianalaskanative" ,
201
+ "rate_overall" ,
202
+ ]
203
+
204
+ for (ageid , sexid , raceid ), expected in zip (ids , expected_list ):
205
+ self .assertEqual (flusurv .groupids_to_name (ageid , sexid , raceid , id_label_map ), expected )
206
+
207
+ with self .assertRaisesRegex (ValueError , "Ageid cannot be 6" ):
208
+ flusurv .groupids_to_name (6 , 0 , 0 , id_label_map )
209
+ with self .assertRaisesRegex (AssertionError , "At most one groupid can be non-zero" ):
210
+ flusurv .groupids_to_name (1 , 1 , 0 , id_label_map )
211
+ flusurv .groupids_to_name (0 , 1 , 1 , id_label_map )
212
+ flusurv .groupids_to_name (1 , 1 , 1 , id_label_map )
0 commit comments