Skip to content

Commit 73d10af

Browse files
committed
Processing tests: allow topological geometry tests instead of exact tests
This is useful with geometry algorithms when the order of the coordinates of produced geometries does not need to be exactly the same every time, but the output is still topologically equivalent.
1 parent 64b8c72 commit 73d10af

File tree

2 files changed

+44
-23
lines changed

2 files changed

+44
-23
lines changed

python/plugins/processing/tests/AlgorithmsTestBase.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,14 @@ def check_results(self, results, context, params, expected):
283283

284284
compare = expected_result.get('compare', {})
285285
pk = expected_result.get('pk', None)
286+
topo_equal_check = expected_result.get('topo_equal_check', False)
286287

287288
if len(expected_lyrs) == 1:
288-
self.assertLayersEqual(expected_lyrs[0], result_lyr, compare=compare, pk=pk)
289+
self.assertLayersEqual(expected_lyrs[0], result_lyr, compare=compare, pk=pk, geometry={'topo_equal_check': topo_equal_check})
289290
else:
290291
res = False
291292
for l in expected_lyrs:
292-
if self.checkLayersEqual(l, result_lyr, compare=compare, pk=pk):
293+
if self.checkLayersEqual(l, result_lyr, compare=compare, pk=pk, geometry={'topo_equal_check': topo_equal_check}):
293294
res = True
294295
break
295296
self.assertTrue(res, 'Could not find matching layer in expected results')
@@ -319,6 +320,7 @@ def check_results(self, results, context, params, expected):
319320

320321

321322
class GenericAlgorithmsTest(unittest.TestCase):
323+
322324
"""
323325
General (non-provider specific) algorithm tests
324326
"""

python/testing/__init__.py

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ def checkLayersEqual(self, layer_expected, layer_result, use_asserts=False, **kw
104104
except KeyError:
105105
precision = 14
106106

107+
try:
108+
topo_equal_check = compare['geometry']['topo_equal_check']
109+
except KeyError:
110+
topo_equal_check = False
111+
107112
def sort_by_pk_or_fid(f):
108113
if 'pk' in kwargs and kwargs['pk'] is not None:
109114
key = kwargs['pk']
@@ -118,27 +123,13 @@ def sort_by_pk_or_fid(f):
118123
result_features = sorted(layer_result.getFeatures(request), key=sort_by_pk_or_fid)
119124

120125
for feats in zip(expected_features, result_features):
121-
if feats[0].hasGeometry():
122-
geom0 = feats[0].geometry().constGet().asWkt(precision)
123-
else:
124-
geom0 = None
125-
if feats[1].hasGeometry():
126-
geom1 = feats[1].geometry().constGet().asWkt(precision)
127-
else:
128-
geom1 = None
129-
if use_asserts:
130-
_TestCase.assertEqual(
131-
self,
132-
geom0,
133-
geom1,
134-
'Features (Expected fid: {}, Result fid: {}) differ in geometry: \n\n Expected geometry:\n {}\n\n Result geometry:\n {}'.format(
135-
feats[0].id(),
136-
feats[1].id(),
137-
geom0,
138-
geom1
139-
)
140-
)
141-
elif geom0 != geom1:
126+
127+
eq = self.checkGeometriesEqual(feats[0].geometry(),
128+
feats[1].geometry(),
129+
feats[0].id(),
130+
feats[1].id(),
131+
use_asserts, precision, topo_equal_check)
132+
if not eq and use_asserts:
142133
return False
143134

144135
for attr_expected, field_expected in zip(feats[0].attributes(), layer_expected.fields().toList()):
@@ -215,6 +206,34 @@ def assertFilesEqual(self, filepath_expected, filepath_result):
215206
diff = list(diff)
216207
self.assertEqual(0, len(diff), ''.join(diff))
217208

209+
def checkGeometriesEqual(self, geom0, geom1, geom0_id, geom1_id, use_asserts=False, precision=14, topo_equal_check=False):
210+
""" Checks whether two geometries are the same - using either a strict check of coordinates (up to given precision)
211+
or by using topological equality (where e.g. a polygon with clockwise is equal to a polygon with counter-clockwise
212+
order of vertices) """
213+
if not geom0.isNull() and not geom1.isNull():
214+
if topo_equal_check:
215+
equal = geom0.isGeosEqual(geom1)
216+
else:
217+
equal = geom0.constGet().asWkt(precision) == geom1.constGet().asWkt(precision)
218+
elif geom0.isNull() and geom1.isNull():
219+
equal = True
220+
else:
221+
equal = False
222+
223+
if use_asserts:
224+
_TestCase.assertTrue(
225+
self,
226+
equal,
227+
'Features (Expected fid: {}, Result fid: {}) differ in geometry: \n\n Expected geometry:\n {}\n\n Result geometry:\n {}'.format(
228+
geom0_id,
229+
geom1_id,
230+
geom0.constGet().asWkt(precision) if geom0 is not None else 'NULL',
231+
geom1.constGet().asWkt(precision) if geom1 is not None else 'NULL'
232+
)
233+
)
234+
else:
235+
return equal
236+
218237

219238
class _UnexpectedSuccess(Exception):
220239

0 commit comments

Comments
 (0)