From 2cda0b478cbff5ae2e7145a1d7acafe2003a8f4a Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Wed, 28 Aug 2024 08:26:46 -0400 Subject: [PATCH] add more tests for identifier and geometry --- pywcmp/wcmp2/ets.py | 22 ++- requirements.txt | 1 + .../wcmp2-failing-invalid-geometry-range.json | 161 ++++++++++++++++++ ...cmp2-failing-invalid-identifier-space.json | 161 ++++++++++++++++++ tests/run_tests.py | 34 ++++ 5 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 tests/data/wcmp2-failing-invalid-geometry-range.json create mode 100644 tests/data/wcmp2-failing-invalid-identifier-space.json diff --git a/pywcmp/wcmp2/ets.py b/pywcmp/wcmp2/ets.py index f2db651..a3e0b66 100644 --- a/pywcmp/wcmp2/ets.py +++ b/pywcmp/wcmp2/ets.py @@ -32,6 +32,7 @@ import uuid from jsonschema.validators import Draft202012Validator +from shapely.geometry import shape import pywcmp from pywcmp.bundle import WCMP2_FILES @@ -169,6 +170,11 @@ def test_requirement_identifier(self): status['message'] = 'bad prefix' return status + if ' ' in identifier_tokens[-1]: + status['code'] = 'FAILED' + status['message'] = 'spaces in local identifier' + return status + centre_id = identifier_tokens[3] if centre_id.endswith('-test'): @@ -228,9 +234,23 @@ def test_requirement_extent_geospatial(self): status = { 'id': gen_test_id('extent_geospatial'), 'code': 'PASSED', - 'message': 'Passes given schema is compliant/valid' } + if self.record['geometry'] is not None: + geometry = shape(self.record['geometry']) + bounds = geometry.bounds + + x_range = range(-180, 180) + y_range = range(-90, 90) + + if not all([bounds[0] in x_range, + bounds[1] in y_range, + bounds[2] in x_range, + bounds[3] in y_range]): + + status['code'] = 'FAILED' + status['messsage'] = 'Invalid geometry' + return status def test_requirement_extent_temporal(self): diff --git a/requirements.txt b/requirements.txt index 62d3b1f..c512889 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ click jsonschema>4.19 pyspellchecker pywis-topics +shapely diff --git a/tests/data/wcmp2-failing-invalid-geometry-range.json b/tests/data/wcmp2-failing-invalid-geometry-range.json new file mode 100644 index 0000000..5c3ea55 --- /dev/null +++ b/tests/data/wcmp2-failing-invalid-geometry-range.json @@ -0,0 +1,161 @@ +{ + "id": "urn:wmo:md:ca-eccc-msc:weather.observations.swob-realtime", + "conformsTo": [ + "http://wis.wmo.int/spec/wcmp/2/conf/core" + ], + "time": { + "interval": [ + "2010-11-11T11:11:11Z", + ".." + ], + "resolution": "P1H" + }, + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -242, + 28 + ], + [ + -142, + 82 + ], + [ + -52, + 82 + ], + [ + -52, + 28 + ], + [ + -142, + 28 + ] + ] + ] + }, + "properties": { + "title": "Surface weather observations", + "description": "Surface Observations measured at the automatic and manual stations of the Environment and Climate Change Canada and partners networks, either for a single station, or for the stations of specific provinces and territories (last 30 days)", + "themes": [ + { + "concepts": [ + { + "id": "Weather" + }, + { + "id": "Archives" + }, + { + "id": "Precipitation" + }, + { + "id": "Air temperature" + }, + { + "id": "Humidity" + }, + { + "id": "Snow" + }, + { + "id": "Wind" + }, + { + "id": "Meteorological data" + } + ], + "scheme": "https://library-archives.canada.ca/eng/services/government-canada/controlled-vocabularies-government-canada/pages/controlled-vocabularies-government-canada.aspx" + }, + { + "concepts": [ + { + "id": "weather" + } + ], + "scheme": "https://codes.wmo.int/wis/topic-hierarchy/earth-system-discipline" + } + ], + "contacts": [ + { + "organization": "Government of Canada; Environment and Climate Change Canada; Meteorological Service of Canada", + "position": "National Inquiry Response Team", + "phones": [ + { + "value": "+18199972800" + } + ], + "emails": [ + { + "value": "enviroinfo@ec.gc.ca" + } + ], + "addresses": [ + { + "deliveryPoint": [ + "77 Westmorland Street, suite 260" + ], + "city": "Fredericton", + "administrativeArea": "NB", + "postalCode": "E3B 6Z4", + "country": "Canada" + } + ], + "links": [ + { + "rel": "canonical", + "type": "text/html", + "href": "https://eccc-msc.github.io/open-data" + } + ], + "contactInstructions": "via email", + "roles": [ + "host", + "producer" + ] + } + ], + "type": "dataset", + "created": "2018-01-01T11:11:11Z", + "updated": "2022-06-22T12:42:46Z", + "wmo:dataPolicy": "core" + }, + "links": [ + { + "rel": "stations", + "href": "https://dd.weather.gc.ca/observations/doc/swob-xml_station_list.csv", + "type": "text/csv", + "title": "Stations associated with this dataset" + }, + { + "rel": "data", + "href": "https://dd.weather.gc.ca/observations/swob-ml", + "type": "text/html", + "hreflang": "en", + "title": "Raw data download (CSV files)" + }, + { + "rel": "items", + "href": "https://api.weather.gc.ca/collections/swob-realtime/items", + "type": "application/json", + "title": "Data access API interface" + }, + { + "rel": "related", + "href": "https://eccc-msc.github.io/open-data/msc-data/obs_station/readme_obs_insitu_swobdatamart_en", + "type": "text/html", + "title": "Documentation" + }, + { + "rel": "items", + "href": "mqtt://example.org:8883", + "channel": "origin/a/wis2/ca-eccc-msc/data/core/weather/surface-based-observations/synop", + "type": "application/json", + "title": "Data notifications" + } + ] +} diff --git a/tests/data/wcmp2-failing-invalid-identifier-space.json b/tests/data/wcmp2-failing-invalid-identifier-space.json new file mode 100644 index 0000000..9ce9b1c --- /dev/null +++ b/tests/data/wcmp2-failing-invalid-identifier-space.json @@ -0,0 +1,161 @@ +{ + "id": "urn:wmo:md:ca-eccc-msc:weather.observations.swob realtime", + "conformsTo": [ + "http://wis.wmo.int/spec/wcmp/2/conf/core" + ], + "time": { + "interval": [ + "2010-11-11T11:11:11Z", + ".." + ], + "resolution": "P1H" + }, + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -142, + 28 + ], + [ + -142, + 82 + ], + [ + -52, + 82 + ], + [ + -52, + 28 + ], + [ + -142, + 28 + ] + ] + ] + }, + "properties": { + "title": "Surface weather observations", + "description": "Surface Observations measured at the automatic and manual stations of the Environment and Climate Change Canada and partners networks, either for a single station, or for the stations of specific provinces and territories (last 30 days)", + "themes": [ + { + "concepts": [ + { + "id": "Weather" + }, + { + "id": "Archives" + }, + { + "id": "Precipitation" + }, + { + "id": "Air temperature" + }, + { + "id": "Humidity" + }, + { + "id": "Snow" + }, + { + "id": "Wind" + }, + { + "id": "Meteorological data" + } + ], + "scheme": "https://library-archives.canada.ca/eng/services/government-canada/controlled-vocabularies-government-canada/pages/controlled-vocabularies-government-canada.aspx" + }, + { + "concepts": [ + { + "id": "weather" + } + ], + "scheme": "https://codes.wmo.int/wis/topic-hierarchy/earth-system-discipline" + } + ], + "contacts": [ + { + "organization": "Government of Canada; Environment and Climate Change Canada; Meteorological Service of Canada", + "position": "National Inquiry Response Team", + "phones": [ + { + "value": "+18199972800" + } + ], + "emails": [ + { + "value": "enviroinfo@ec.gc.ca" + } + ], + "addresses": [ + { + "deliveryPoint": [ + "77 Westmorland Street, suite 260" + ], + "city": "Fredericton", + "administrativeArea": "NB", + "postalCode": "E3B 6Z4", + "country": "Canada" + } + ], + "links": [ + { + "rel": "canonical", + "type": "text/html", + "href": "https://eccc-msc.github.io/open-data" + } + ], + "contactInstructions": "via email", + "roles": [ + "host", + "producer" + ] + } + ], + "type": "dataset", + "created": "2018-01-01T11:11:11Z", + "updated": "2022-06-22T12:42:46Z", + "wmo:dataPolicy": "core" + }, + "links": [ + { + "rel": "stations", + "href": "https://dd.weather.gc.ca/observations/doc/swob-xml_station_list.csv", + "type": "text/csv", + "title": "Stations associated with this dataset" + }, + { + "rel": "data", + "href": "https://dd.weather.gc.ca/observations/swob-ml", + "type": "text/html", + "hreflang": "en", + "title": "Raw data download (CSV files)" + }, + { + "rel": "items", + "href": "https://api.weather.gc.ca/collections/swob-realtime/items", + "type": "application/json", + "title": "Data access API interface" + }, + { + "rel": "related", + "href": "https://eccc-msc.github.io/open-data/msc-data/obs_station/readme_obs_insitu_swobdatamart_en", + "type": "text/html", + "title": "Documentation" + }, + { + "rel": "items", + "href": "mqtt://example.org:8883", + "channel": "origin/a/wis2/ca-eccc-msc/data/core/weather/surface-based-observations/synop", + "type": "application/json", + "title": "Data notifications" + } + ] +} diff --git a/tests/run_tests.py b/tests/run_tests.py index 004e991..f75880f 100644 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -145,6 +145,40 @@ def test_fail_invalid_link_channel_wis2_topic(self): self.assertEqual(codes.count('PASSED'), 11) self.assertEqual(codes.count('SKIPPED'), 0) + def test_fail_invalid_identifier_space(self): + """ + Simple tests for a failing record with an invalid + identifier (space in local identifier) + """ + + with open(get_test_file_path('data/wcmp2-failing-invalid-identifier-space.json')) as fh: # noqa + record = json.load(fh) + ts = WMOCoreMetadataProfileTestSuite2(record) + results = ts.run_tests() + + codes = [r['code'] for r in results['tests']] + + self.assertEqual(codes.count('FAILED'), 1) + self.assertEqual(codes.count('PASSED'), 11) + self.assertEqual(codes.count('SKIPPED'), 0) + + def test_fail_invalid_geometry_range(self): + """ + Simple tests for a failing record with an invalid + geometry (values out of WGS84 range) + """ + + with open(get_test_file_path('data/wcmp2-failing-invalid-geometry-range.json')) as fh: # noqa + record = json.load(fh) + ts = WMOCoreMetadataProfileTestSuite2(record) + results = ts.run_tests() + + codes = [r['code'] for r in results['tests']] + + self.assertEqual(codes.count('FAILED'), 1) + self.assertEqual(codes.count('PASSED'), 11) + self.assertEqual(codes.count('SKIPPED'), 0) + class WCMP2KPITest(unittest.TestCase): """WCMP KPI tests of tests"""