From d4ad063f45b32191d320620d2bf1c4b54c1a1359 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sat, 5 Aug 2017 22:10:18 +1000 Subject: [PATCH] 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. --- .../processing/tests/AlgorithmsTestBase.py | 5 +++-- .../tests/testdata/qgis_algorithm_tests.yaml | 4 ++++ python/testing/__init__.py | 18 ++++++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/python/plugins/processing/tests/AlgorithmsTestBase.py b/python/plugins/processing/tests/AlgorithmsTestBase.py index 2ae126ccbf6..2e19146a7b7 100644 --- a/python/plugins/processing/tests/AlgorithmsTestBase.py +++ b/python/plugins/processing/tests/AlgorithmsTestBase.py @@ -287,13 +287,14 @@ class AlgorithmsTest(object): self.assertTrue(result_lyr, results[id]) compare = expected_result.get('compare', {}) + pk = expected_result.get('pk', None) 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: res = False 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 break self.assertTrue(res, 'Could not find matching layer in expected results') diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml index 215160793c6..79378a18d39 100644 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml @@ -2501,6 +2501,10 @@ tests: OUTPUT: name: expected/stats_by_category.gml type: vector + pk: id2 + compare: + fields: + fid: skip # - algorithm: qgis:zonalstatistics # name: simple zonal statistics diff --git a/python/testing/__init__.py b/python/testing/__init__.py index a495a335681..fc3eafe1fa0 100644 --- a/python/testing/__init__.py +++ b/python/testing/__init__.py @@ -54,6 +54,10 @@ class TestCase(_TestCase): :keyword compare: A map of comparison options. e.g. { fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } } { 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) @@ -69,6 +73,10 @@ class TestCase(_TestCase): :keyword compare: A map of comparison options. e.g. { fields: { a: skip, b: { precision: 2 }, geometry: { precision: 5 } } { 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: @@ -98,8 +106,14 @@ class TestCase(_TestCase): except KeyError: precision = 14 - expected_features = sorted(layer_expected.getFeatures(request), key=lambda f: f.id()) - result_features = sorted(layer_result.getFeatures(request), key=lambda f: f.id()) + def sort_by_pk_or_fid(f): + 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): if feats[0].hasGeometry():