Skip to content

Commit

Permalink
Processing tests: allow topological geometry tests instead of exact t…
Browse files Browse the repository at this point in the history
…ests

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.
  • Loading branch information
wonder-sk committed May 10, 2018
1 parent 64b8c72 commit 73d10af
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 23 deletions.
6 changes: 4 additions & 2 deletions python/plugins/processing/tests/AlgorithmsTestBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,14 @@ def check_results(self, results, context, params, expected):

compare = expected_result.get('compare', {})
pk = expected_result.get('pk', None)
topo_equal_check = expected_result.get('topo_equal_check', False)

if len(expected_lyrs) == 1:
self.assertLayersEqual(expected_lyrs[0], result_lyr, compare=compare, pk=pk)
self.assertLayersEqual(expected_lyrs[0], result_lyr, compare=compare, pk=pk, geometry={'topo_equal_check': topo_equal_check})
else:
res = False
for l in expected_lyrs:
if self.checkLayersEqual(l, result_lyr, compare=compare, pk=pk):
if self.checkLayersEqual(l, result_lyr, compare=compare, pk=pk, geometry={'topo_equal_check': topo_equal_check}):
res = True
break
self.assertTrue(res, 'Could not find matching layer in expected results')
Expand Down Expand Up @@ -319,6 +320,7 @@ def check_results(self, results, context, params, expected):


class GenericAlgorithmsTest(unittest.TestCase):

"""
General (non-provider specific) algorithm tests
"""
Expand Down
61 changes: 40 additions & 21 deletions python/testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ def checkLayersEqual(self, layer_expected, layer_result, use_asserts=False, **kw
except KeyError:
precision = 14

try:
topo_equal_check = compare['geometry']['topo_equal_check']
except KeyError:
topo_equal_check = False

def sort_by_pk_or_fid(f):
if 'pk' in kwargs and kwargs['pk'] is not None:
key = kwargs['pk']
Expand All @@ -118,27 +123,13 @@ def sort_by_pk_or_fid(f):
result_features = sorted(layer_result.getFeatures(request), key=sort_by_pk_or_fid)

for feats in zip(expected_features, result_features):
if feats[0].hasGeometry():
geom0 = feats[0].geometry().constGet().asWkt(precision)
else:
geom0 = None
if feats[1].hasGeometry():
geom1 = feats[1].geometry().constGet().asWkt(precision)
else:
geom1 = None
if use_asserts:
_TestCase.assertEqual(
self,
geom0,
geom1,
'Features (Expected fid: {}, Result fid: {}) differ in geometry: \n\n Expected geometry:\n {}\n\n Result geometry:\n {}'.format(
feats[0].id(),
feats[1].id(),
geom0,
geom1
)
)
elif geom0 != geom1:

eq = self.checkGeometriesEqual(feats[0].geometry(),
feats[1].geometry(),
feats[0].id(),
feats[1].id(),
use_asserts, precision, topo_equal_check)
if not eq and use_asserts:
return False

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

def checkGeometriesEqual(self, geom0, geom1, geom0_id, geom1_id, use_asserts=False, precision=14, topo_equal_check=False):
""" Checks whether two geometries are the same - using either a strict check of coordinates (up to given precision)
or by using topological equality (where e.g. a polygon with clockwise is equal to a polygon with counter-clockwise
order of vertices) """
if not geom0.isNull() and not geom1.isNull():
if topo_equal_check:
equal = geom0.isGeosEqual(geom1)
else:
equal = geom0.constGet().asWkt(precision) == geom1.constGet().asWkt(precision)
elif geom0.isNull() and geom1.isNull():
equal = True
else:
equal = False

if use_asserts:
_TestCase.assertTrue(
self,
equal,
'Features (Expected fid: {}, Result fid: {}) differ in geometry: \n\n Expected geometry:\n {}\n\n Result geometry:\n {}'.format(
geom0_id,
geom1_id,
geom0.constGet().asWkt(precision) if geom0 is not None else 'NULL',
geom1.constGet().asWkt(precision) if geom1 is not None else 'NULL'
)
)
else:
return equal


class _UnexpectedSuccess(Exception):

Expand Down

0 comments on commit 73d10af

Please sign in to comment.