1919)
2020
2121
22+ def mock_request (httpx_mock , request_url , file_path ):
23+ with open (file_path ) as text :
24+ httpx_mock .add_response (
25+ method = "GET" ,
26+ url = request_url ,
27+ text = text .read (),
28+ headers = {"mock_header" : "value" },
29+ )
30+
31+
32+ def _assert_wqp_metadata (md , request_url ):
33+ """The metadata assertions shared by every mocked WQP query."""
34+ assert md .url == request_url
35+ assert isinstance (md .query_time , datetime .timedelta )
36+ assert md .header .get ("mock_header" ) == "value"
37+ assert md .comment is None
38+
39+
2240def test_read_wqp_csv_preserves_leading_zero_codes ():
2341 """Regression: WQP code columns (HUCs, parameter codes, FIPS) carry
2442 significant leading zeros; a bare ``read_csv`` inferred them as int/float
@@ -52,10 +70,7 @@ def test_get_results(httpx_mock):
5270 )
5371 assert type (df ) is DataFrame
5472 assert df .shape == (5 , 65 )
55- assert md .url == request_url
56- assert isinstance (md .query_time , datetime .timedelta )
57- assert md .header .get ("mock_header" ) == "value"
58- assert md .comment is None
73+ _assert_wqp_metadata (md , request_url )
5974 assert df ["ActivityStartDateTime" ].notna ().all ()
6075 # Regression: the getter must thread the query kwargs into the metadata
6176 # (it previously built WQP_Metadata(response), dropping them), so that
@@ -82,157 +97,52 @@ def test_get_results_WQX3(httpx_mock):
8297 )
8398 assert type (df ) is DataFrame
8499 assert df .shape == (5 , 186 )
85- assert md .url == request_url
86- assert isinstance (md .query_time , datetime .timedelta )
87- assert md .header .get ("mock_header" ) == "value"
88- assert md .comment is None
100+ _assert_wqp_metadata (md , request_url )
89101 assert df ["Activity_StartDateTime" ].notna ().all ()
90102
91103
92- def test_what_sites (httpx_mock ):
93- """Tests Water quality portal sites query"""
94- request_url = (
95- "https://www.waterqualitydata.us/data/Station/Search?statecode=US%3A34&characteristicName=Chloride"
96- "&mimeType=csv"
97- )
98- response_file_path = "tests/data/wqp_sites.txt"
99- mock_request (httpx_mock , request_url , response_file_path )
100- df , md = what_sites (statecode = "US:34" , characteristicName = "Chloride" )
101- assert type (df ) is DataFrame
102- assert df .size == 239868
103- assert md .url == request_url
104- assert isinstance (md .query_time , datetime .timedelta )
105- assert md .header .get ("mock_header" ) == "value"
106- assert md .comment is None
107-
108-
109- def test_what_organizations (httpx_mock ):
110- """Tests Water quality portal organizations query"""
111- request_url = (
112- "https://www.waterqualitydata.us/data/Organization/Search?statecode=US%3A34&characteristicName=Chloride"
113- "&mimeType=csv"
114- )
115- response_file_path = "tests/data/wqp_organizations.txt"
116- mock_request (httpx_mock , request_url , response_file_path )
117- df , md = what_organizations (statecode = "US:34" , characteristicName = "Chloride" )
118- assert type (df ) is DataFrame
119- assert df .size == 576
120- assert md .url == request_url
121- assert isinstance (md .query_time , datetime .timedelta )
122- assert md .header .get ("mock_header" ) == "value"
123- assert md .comment is None
124-
125-
126- def test_what_projects (httpx_mock ):
127- """Tests Water quality portal projects query"""
128- request_url = (
129- "https://www.waterqualitydata.us/data/Project/Search?statecode=US%3A34&characteristicName=Chloride"
130- "&mimeType=csv"
131- )
132- response_file_path = "tests/data/wqp_projects.txt"
133- mock_request (httpx_mock , request_url , response_file_path )
134- df , md = what_projects (statecode = "US:34" , characteristicName = "Chloride" )
135- assert type (df ) is DataFrame
136- assert df .size == 530
137- assert md .url == request_url
138- assert isinstance (md .query_time , datetime .timedelta )
139- assert md .header .get ("mock_header" ) == "value"
140- assert md .comment is None
141-
142-
143- def test_what_activities (httpx_mock ):
144- """Tests Water quality portal activities query"""
145- request_url = (
146- "https://www.waterqualitydata.us/data/Activity/Search?statecode=US%3A34&characteristicName=Chloride"
147- "&mimeType=csv"
148- )
149- response_file_path = "tests/data/wqp_activities.txt"
150- mock_request (httpx_mock , request_url , response_file_path )
151- df , md = what_activities (statecode = "US:34" , characteristicName = "Chloride" )
152- assert type (df ) is DataFrame
153- assert df .size == 5087443
154- assert md .url == request_url
155- assert isinstance (md .query_time , datetime .timedelta )
156- assert md .header .get ("mock_header" ) == "value"
157- assert md .comment is None
158-
159-
160- def test_what_detection_limits (httpx_mock ):
161- """Tests Water quality portal detection limits query"""
162- request_url = (
163- "https://www.waterqualitydata.us/data/ResultDetectionQuantitationLimit/Search?statecode=US%3A34&characteristicName=Chloride"
164- "&mimeType=csv"
165- )
166- response_file_path = "tests/data/wqp_detection_limits.txt"
167- mock_request (httpx_mock , request_url , response_file_path )
168- df , md = what_detection_limits (statecode = "US:34" , characteristicName = "Chloride" )
169- assert type (df ) is DataFrame
170- assert df .size == 98770
171- assert md .url == request_url
172- assert isinstance (md .query_time , datetime .timedelta )
173- assert md .header .get ("mock_header" ) == "value"
174- assert md .comment is None
175-
176-
177- def test_what_habitat_metrics (httpx_mock ):
178- """Tests Water quality portal habitat metrics query"""
179- request_url = (
180- "https://www.waterqualitydata.us/data/BiologicalMetric/Search?statecode=US%3A34&characteristicName=Chloride"
181- "&mimeType=csv"
182- )
183- response_file_path = "tests/data/wqp_habitat_metrics.txt"
184- mock_request (httpx_mock , request_url , response_file_path )
185- df , md = what_habitat_metrics (statecode = "US:34" , characteristicName = "Chloride" )
186- assert type (df ) is DataFrame
187- assert df .size == 48114
188- assert md .url == request_url
189- assert isinstance (md .query_time , datetime .timedelta )
190- assert md .header .get ("mock_header" ) == "value"
191- assert md .comment is None
192-
193-
194- def test_what_project_weights (httpx_mock ):
195- """Tests Water quality portal project weights query"""
196- request_url = (
197- "https://www.waterqualitydata.us/data/ProjectMonitoringLocationWeighting/Search?statecode=US%3A34&characteristicName=Chloride"
198- "&mimeType=csv"
199- )
200- response_file_path = "tests/data/wqp_project_weights.txt"
201- mock_request (httpx_mock , request_url , response_file_path )
202- df , md = what_project_weights (statecode = "US:34" , characteristicName = "Chloride" )
203- assert type (df ) is DataFrame
204- assert df .size == 33098
205- assert md .url == request_url
206- assert isinstance (md .query_time , datetime .timedelta )
207- assert md .header .get ("mock_header" ) == "value"
208- assert md .comment is None
209-
210-
211- def test_what_activity_metrics (httpx_mock ):
212- """Tests Water quality portal activity metrics query"""
104+ # Every WQP ``what_*`` wrapper issues the same query against its own service
105+ # endpoint and returns the parsed DataFrame + metadata; they differ only by the
106+ # service path segment, the response fixture, and the expected size.
107+ _WHAT_CASES = [
108+ (what_sites , "Station" , "wqp_sites.txt" , 239868 ),
109+ (what_organizations , "Organization" , "wqp_organizations.txt" , 576 ),
110+ (what_projects , "Project" , "wqp_projects.txt" , 530 ),
111+ (what_activities , "Activity" , "wqp_activities.txt" , 5087443 ),
112+ (
113+ what_detection_limits ,
114+ "ResultDetectionQuantitationLimit" ,
115+ "wqp_detection_limits.txt" ,
116+ 98770 ,
117+ ),
118+ (what_habitat_metrics , "BiologicalMetric" , "wqp_habitat_metrics.txt" , 48114 ),
119+ (
120+ what_project_weights ,
121+ "ProjectMonitoringLocationWeighting" ,
122+ "wqp_project_weights.txt" ,
123+ 33098 ,
124+ ),
125+ (what_activity_metrics , "ActivityMetric" , "wqp_activity_metrics.txt" , 378 ),
126+ ]
127+
128+
129+ @pytest .mark .parametrize (
130+ "func, service, fixture, size" ,
131+ _WHAT_CASES ,
132+ ids = [case [0 ].__name__ for case in _WHAT_CASES ],
133+ )
134+ def test_what_query (httpx_mock , func , service , fixture , size ):
135+ """Each WQP ``what_*`` wrapper hits its own service endpoint and returns the
136+ parsed DataFrame + metadata."""
213137 request_url = (
214- "https://www.waterqualitydata.us/data/ActivityMetric /Search?statecode=US%3A34&characteristicName=Chloride "
215- "&mimeType=csv"
138+ f "https://www.waterqualitydata.us/data/{ service } /Search?"
139+ "statecode=US%3A34&characteristicName=Chloride &mimeType=csv"
216140 )
217- response_file_path = "tests/data/wqp_activity_metrics.txt"
218- mock_request (httpx_mock , request_url , response_file_path )
219- df , md = what_activity_metrics (statecode = "US:34" , characteristicName = "Chloride" )
141+ mock_request (httpx_mock , request_url , f"tests/data/{ fixture } " )
142+ df , md = func (statecode = "US:34" , characteristicName = "Chloride" )
220143 assert type (df ) is DataFrame
221- assert df .size == 378
222- assert md .url == request_url
223- assert isinstance (md .query_time , datetime .timedelta )
224- assert md .header .get ("mock_header" ) == "value"
225- assert md .comment is None
226-
227-
228- def mock_request (httpx_mock , request_url , file_path ):
229- with open (file_path ) as text :
230- httpx_mock .add_response (
231- method = "GET" ,
232- url = request_url ,
233- text = text .read (),
234- headers = {"mock_header" : "value" },
235- )
144+ assert df .size == size
145+ _assert_wqp_metadata (md , request_url )
236146
237147
238148def test_check_kwargs ():
0 commit comments