Allow specifying a 'primary key' field when comparing layers for

processing tests

Some algorithms will return results in different orders, e.g.
due to the use of dicts or other methods which do not guarantee
a fixed return order.

Using a primary key to do the feature match allows us to flexibly
handle these situations and provide tests for these algorithms.
This commit is contained in:
Nyall Dawson 2017-08-05 22:10:18 +10:00
parent 6aa672d9e0
commit d4ad063f45
3 changed files with 23 additions and 4 deletions

View File

@ -287,13 +287,14 @@ class AlgorithmsTest(object):
self.assertTrue(result_lyr, results[id]) self.assertTrue(result_lyr, results[id])
compare = expected_result.get('compare', {}) compare = expected_result.get('compare', {})
pk = expected_result.get('pk', None)
if len(expected_lyrs) == 1: if len(expected_lyrs) == 1:
self.assertLayersEqual(expected_lyrs[0], result_lyr, compare=compare) self.assertLayersEqual(expected_lyrs[0], result_lyr, compare=compare, pk=pk)
else: else:
res = False res = False
for l in expected_lyrs: for l in expected_lyrs:
if self.checkLayersEqual(l, result_lyr, compare=compare): if self.checkLayersEqual(l, result_lyr, compare=compare, pk=pk):
res = True res = True
break break
self.assertTrue(res, 'Could not find matching layer in expected results') self.assertTrue(res, 'Could not find matching layer in expected results')

View File

@ -2501,6 +2501,10 @@ tests:
OUTPUT: OUTPUT:
name: expected/stats_by_category.gml name: expected/stats_by_category.gml
type: vector type: vector
pk: id2
compare:
fields:
fid: skip
# - algorithm: qgis:zonalstatistics # - algorithm: qgis:zonalstatistics
# name: simple zonal statistics # name: simple zonal statistics

View File

@ -54,6 +54,10 @@ class TestCase(_TestCase):
:keyword compare: A map of comparison options. e.g. :keyword compare: A map of comparison options. e.g.
{ fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } } { fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } }
{ fields: { __all__: cast( str ) } } { fields: { __all__: cast( str ) } }
:keyword pk: "Primary key" type field - used to match features
from the expected table to their corresponding features in the result table. If not specified
features are compared by their order in the layer (e.g. first feature compared with first feature,
etc)
""" """
self.checkLayersEqual(layer_expected, layer_result, True, **kwargs) self.checkLayersEqual(layer_expected, layer_result, True, **kwargs)
@ -69,6 +73,10 @@ class TestCase(_TestCase):
:keyword compare: A map of comparison options. e.g. :keyword compare: A map of comparison options. e.g.
{ fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } } { fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } }
{ fields: { __all__: cast( str ) } } { fields: { __all__: cast( str ) } }
:keyword pk: "Primary key" type field - used to match features
from the expected table to their corresponding features in the result table. If not specified
features are compared by their order in the layer (e.g. first feature compared with first feature,
etc)
""" """
try: try:
@ -98,8 +106,14 @@ class TestCase(_TestCase):
except KeyError: except KeyError:
precision = 14 precision = 14
expected_features = sorted(layer_expected.getFeatures(request), key=lambda f: f.id()) def sort_by_pk_or_fid(f):
result_features = sorted(layer_result.getFeatures(request), key=lambda f: f.id()) if 'pk' in kwargs and kwargs['pk'] is not None:
return f[kwargs['pk']]
else:
return f.id()
expected_features = sorted(layer_expected.getFeatures(request), key=sort_by_pk_or_fid)
result_features = sorted(layer_result.getFeatures(request), key=sort_by_pk_or_fid)
for feats in zip(expected_features, result_features): for feats in zip(expected_features, result_features):
if feats[0].hasGeometry(): if feats[0].hasGeometry():