From: Sarah Hoffmann Date: Thu, 9 Mar 2023 15:36:46 +0000 (+0100) Subject: bdd: fully check correctness of geojson and geocodejson X-Git-Tag: v4.3.0~90^2~13 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/fbff4fa2187f14e1aa55f92ff4f9866a769ef808?ds=inline bdd: fully check correctness of geojson and geocodejson Parse code now checks presence of all required fields and exports all fields for inspection. --- diff --git a/test/bdd/steps/check_functions.py b/test/bdd/steps/check_functions.py index f214a886..1a6f08ef 100644 --- a/test/bdd/steps/check_functions.py +++ b/test/bdd/steps/check_functions.py @@ -7,6 +7,7 @@ """ Collection of assertion functions used for the steps. """ +import json class Almost: """ Compares a float value with a certain jitter. @@ -41,3 +42,24 @@ class Bbox: def __str__(self): return str(self.coord) + + + +def check_for_attributes(obj, attrs, presence='present'): + """ Check that the object has the given attributes. 'attrs' is a + string with a comma-separated list of attributes. If 'presence' + is set to 'absent' then the function checks that the attributes do + not exist for the object + """ + def _dump_json(): + return json.dumps(obj, sort_keys=True, indent=2, ensure_ascii=False) + + for attr in attrs.split(','): + attr = attr.strip() + if presence == 'absent': + assert attr not in obj, \ + f"Unexpected attribute {attr}. Full response:\n{_dump_json()}" + else: + assert attr in obj, \ + f"No attribute '{attr}'. Full response:\n{_dump_json()}" + diff --git a/test/bdd/steps/http_responses.py b/test/bdd/steps/http_responses.py index dcce1b58..aee0d7f0 100644 --- a/test/bdd/steps/http_responses.py +++ b/test/bdd/steps/http_responses.py @@ -11,7 +11,7 @@ import re import json import xml.etree.ElementTree as ET -from check_functions import Almost +from check_functions import Almost, check_for_attributes OSM_TYPE = {'N' : 'node', 'W' : 'way', 'R' : 'relation', 'n' : 'node', 'w' : 'way', 'r' : 'relation', @@ -76,15 +76,47 @@ class GenericResponse: else: self.result = [self.result] + def _parse_geojson(self): self._parse_json() if self.result: - self.result = list(map(_geojson_result_to_json_result, self.result[0]['features'])) + geojson = self.result[0] + # check for valid geojson + check_for_attributes(geojson, 'type,features') + assert geojson['type'] == 'FeatureCollection' + assert isinstance(geojson['features'], list) + + self.result = [] + for result in geojson['features']: + check_for_attributes(result, 'type,properties,geometry') + assert result['type'] == 'Feature' + new = result['properties'] + check_for_attributes(new, 'geojson', 'absent') + new['geojson'] = result['geometry'] + if 'bbox' in result: + check_for_attributes(new, 'boundingbox', 'absent') + # bbox is minlon, minlat, maxlon, maxlat + # boundingbox is minlat, maxlat, minlon, maxlon + new['boundingbox'] = [result['bbox'][1], + result['bbox'][3], + result['bbox'][0], + result['bbox'][2]] + for k, v in geojson.items(): + if k not in ('type', 'features'): + check_for_attributes(new, '__' + k, 'absent') + new['__' + k] = v + self.result.append(new) + def _parse_geocodejson(self): self._parse_geojson() - if self.result is not None: - self.result = [r['geocoding'] for r in self.result] + if self.result: + for r in self.result: + assert set(r.keys()) == {'geocoding', 'geojson', '__geocoding'}, \ + f"Unexpected keys in result: {r.keys()}" + check_for_attributes(r['geocoding'], 'geojson', 'absent') + r |= r.pop('geocoding') + def assert_field(self, idx, field, value): """ Check that result row `idx` has a field `field` with value `value`.