diff --git a/src/open_irceline/api.py b/src/open_irceline/api.py index 0abb628..a3d9a29 100644 --- a/src/open_irceline/api.py +++ b/src/open_irceline/api.py @@ -253,6 +253,6 @@ class IrcelineForecastClient(IrcelineBaseClient): try: if x == float(row[1]) and y == float(row[2]): return float(row[3]) - except ValueError: + except (ValueError, IndexError): continue return None diff --git a/tests/conftest.py b/tests/conftest.py index 826ba28..da3b13f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,8 @@ import json -def get_api_data(fixture: str) -> dict: +def get_api_data(fixture: str, plain=False) -> str | dict: with open(f'tests/fixtures/{fixture}', 'r') as file: + if plain: + return file.read() return json.load(file) diff --git a/tests/fixtures/forecast.csv b/tests/fixtures/forecast.csv new file mode 100644 index 0000000..58e586d --- /dev/null +++ b/tests/fixtures/forecast.csv @@ -0,0 +1,35 @@ +id;lat;lon;value +1076;51.25;4.8;20.2708 +1077;51.3;4.8;20.0029 +1078;51.35;4.8;19.7267 +1079;51.4;4.8;19.4676 +1080;51.45;4.8;19.251 +1081;51.5;4.8;crazy +Not a valid line you know :) +1082;51.55;4.8;19.0408 +1083;51.6;4.8;19.0502 +1084;49.7;4.85;4.42709 +1085;49.75;4.85;4.37795 +1086;49.8;4.85;4.38195 +1087;49.85;4.85;4.45616 +1088;49.9;4.85;4.61764 +1089;49.95;4.85;4.88348 +1090;50;4.85;5.2708 +1091;50.05;4.85;5.81261 +1092;50.1;4.85;6.50964 +1093;50.15;4.85;7.33034 +1094;50.2;4.85;8.24316 +1095;50.25;4.85;9.21653 +1096;50.3;4.85;10.2189 +1097;50.35;4.85;11.2187 +1098;50.4;4.85;12.1844 +1099;50.45;4.85;13.0844 +1100;50.5;4.85;13.8872 +1101;50.55;4.85;14.6399 +1102;50.6;4.85;15.4015 +1103;50.65;4.85;16.1581 +1104;50.7;4.85;16.8957 +1105;50.75;4.85;17.6005 +1106;50.8;4.85;18.2584 +1107;50.85;4.85;18.8555 +1108;50.9;4.85;19.3779 \ No newline at end of file diff --git a/tests/fixtures/rio_wfs_with_errors.json b/tests/fixtures/rio_wfs_with_errors.json new file mode 100644 index 0000000..410cc2f --- /dev/null +++ b/tests/fixtures/rio_wfs_with_errors.json @@ -0,0 +1,236 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "no2_hmean.fid-280be381_1901cca3e5c_4c81", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 182000, + 128000 + ], + [ + 182000, + 132000 + ], + [ + 186000, + 132000 + ], + [ + 186000, + 128000 + ], + [ + 182000, + 128000 + ] + ] + ] + }, + "geometry_name": "the_geom", + "properties": { + "id": 1102, + "value": 4, + "network": "Wallonia" + } + }, + { + "type": "Feature", + "id": "no2_hmean.fid-280be381_1901cca3e5c_4c82", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 182000, + 128000 + ], + [ + 182000, + 132000 + ], + [ + 186000, + 132000 + ], + [ + 186000, + 128000 + ], + [ + 182000, + 128000 + ] + ] + ] + }, + "geometry_name": "the_geom", + "properties": { + "id": 1102, + "timestamp": "2024-06-15T16:00:00Z--", + "value": 4, + "network": "Wallonia" + } + }, + { + "type": "Feature", + "id": "pm25_hmean.fid-280be381_1901cca3e5c_4c83", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 182000, + 128000 + ], + [ + 182000, + 132000 + ], + [ + 186000, + 132000 + ], + [ + 186000, + 128000 + ], + [ + 182000, + 128000 + ] + ] + ] + }, + "geometry_name": "the_geom", + "properties": { + "id": 1102, + "timestamp": "2024-06-15T15:00:00Z", + "value": 1, + "network": "Wallonia" + } + }, + { + "type": "Feature", + "id": "pm25_hmean.fid-280be381_1901cca3e5c_4c84", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 182000, + 128000 + ], + [ + 182000, + 132000 + ], + [ + 186000, + 132000 + ], + [ + 186000, + 128000 + ], + [ + 182000, + 128000 + ] + ] + ] + }, + "geometry_name": "the_geom" + }, + { + "type": "Feature", + "id": "o3_hmean.fid-280be381_1901cca3e5c_4c85", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 182000, + 128000 + ], + [ + 182000, + 132000 + ], + [ + 186000, + 132000 + ], + [ + 186000, + 128000 + ], + [ + 182000, + 128000 + ] + ] + ] + }, + "geometry_name": "the_geom", + "properties": { + "id": 1102, + "timestamp": "2024-06-15T15:00:00Z", + "value": 74, + "network": "Wallonia" + } + }, + { + "type": "Feature", + "id": "o3_hmean.fid-280be381_1901cca3e5c_4c86", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 182000, + 128000 + ], + [ + 182000, + 132000 + ], + [ + 186000, + 132000 + ], + [ + 186000, + 128000 + ], + [ + 182000, + 128000 + ] + ] + ] + }, + "geometry_name": "the_geom", + "properties": { + "id": 1102, + "timestamp": "2024-06-15T16:00:00Z", + "value": 71, + "network": "Wallonia" + } + } + ], + "totalFeatures": 6, + "numberMatched": 6, + "numberReturned": 6, + "timeStamp": "2024-06-15T16:55:03.419Z", + "crs": { + "type": "name", + "properties": { + "name": "urn:ogc:def:crs:EPSG::31370" + } + } +} diff --git a/tests/test_api_forecasts.py b/tests/test_api_forecasts.py new file mode 100644 index 0000000..ba27c98 --- /dev/null +++ b/tests/test_api_forecasts.py @@ -0,0 +1,13 @@ +from src.open_irceline.api import IrcelineForecastClient +from tests.conftest import get_api_data + + +def test_extract_from_csv(): + data = get_api_data('forecast.csv', plain=True) + x, y = 50.45, 4.85 + + result = IrcelineForecastClient.extract_result_from_csv(x, y, data) + assert result == 13.0844 + + result = IrcelineForecastClient.extract_result_from_csv(23, 4, data) + assert result is None diff --git a/tests/test_api.py b/tests/test_api_rio.py similarity index 75% rename from tests/test_api.py rename to tests/test_api_rio.py index 864fe64..4fefa5a 100644 --- a/tests/test_api.py +++ b/tests/test_api_rio.py @@ -26,6 +26,26 @@ async def test_format_result_hmean(): assert result == expected +@freeze_time(datetime.fromisoformat("2024-06-15T16:55:03.419Z")) +async def test_format_result_hmean_with_error(): + data = get_api_data('rio_wfs_with_errors.json') + result = IrcelineRioClient._format_result('rio', data, + [RioFeature.NO2_HMEAN, RioFeature.O3_HMEAN, RioFeature.PM25_HMEAN]) + + expected = { + str(RioFeature.O3_HMEAN): FeatureValue( + timestamp=datetime.fromisoformat("2024-06-15T16:00:00Z"), + value=71 + ), + str(RioFeature.PM25_HMEAN): FeatureValue( + timestamp=datetime.fromisoformat("2024-06-15T15:00:00Z"), + value=1 + ) + } + + assert result == expected + + @freeze_time(datetime.fromisoformat("2024-06-15T19:30:09.581Z")) async def test_format_result_dmean(): data = get_api_data('rio_wfs_dmean.json') @@ -42,8 +62,8 @@ async def test_format_result_dmean(): def test_parse_capabilities(): - with open('tests/fixtures/capabilities.xml', 'r') as xml_file: - result = IrcelineRioClient._parse_capabilities(xml_file.read()) + data = get_api_data('capabilities.xml', plain=True) + result = IrcelineRioClient._parse_capabilities(data) expected = {'rio:so2_anmean_be', 'rio:o3_hmean', 'rio:bc_anmean_vl', 'rio:o3_anmean_be', 'rio:pm10_hmean_vl', 'rio:o3_aot40for_be', 'rio:no2_maxhmean', 'rio:pm10_24hmean_1x1', 'rio:o3_aot40veg_5y_be', @@ -62,4 +82,7 @@ def test_parse_capabilities(): assert result == expected -# TODO add new tests for IrcelineForecastClient + +def test_parse_capabilities_with_error(): + result = IrcelineRioClient._parse_capabilities("wow there no valid XML") + assert result == set()