# -*- coding: utf-8 -*- """QGIS Unit tests for Processing CheckValidity algorithm. .. note:: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. """ __author__ = 'Alessandro Pasotti' __date__ = '2018-09' __copyright__ = 'Copyright 2018, The QGIS Project' from qgis.PyQt.QtCore import QCoreApplication, QVariant from qgis.core import ( QgsFeature, QgsGeometry, QgsApplication, QgsMemoryProviderUtils, QgsWkbTypes, QgsField, QgsFields, QgsProcessingContext, QgsProcessingFeedback, QgsCoordinateReferenceSystem, QgsProject, QgsProcessingException, QgsProcessingUtils, QgsSettings ) from processing.core.Processing import Processing from processing.gui.AlgorithmExecutor import execute from qgis.testing import start_app, unittest from qgis.PyQt.QtTest import QSignalSpy from qgis.analysis import QgsNativeAlgorithms start_app() class ConsoleFeedBack(QgsProcessingFeedback): def reportError(self, error, fatalError=False): print(error) class TestQgsProcessingCheckValidity(unittest.TestCase): @classmethod def setUpClass(cls): """Run before all tests""" QCoreApplication.setOrganizationName("QGIS_Test") QCoreApplication.setOrganizationDomain( "QGIS_TestPyQgsProcessingCheckValidity.com") QCoreApplication.setApplicationName( "QGIS_TestPyQgsProcessingCheckValidity") QgsSettings().clear() Processing.initialize() QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms()) cls.registry = QgsApplication.instance().processingRegistry() def _make_layer(self, layer_wkb_name): fields = QgsFields() wkb_type = getattr(QgsWkbTypes, layer_wkb_name) fields.append(QgsField('int_f', QVariant.Int)) layer = QgsMemoryProviderUtils.createMemoryLayer( '%s_layer' % layer_wkb_name, fields, wkb_type, QgsCoordinateReferenceSystem(4326)) self.assertTrue(layer.isValid()) self.assertEqual(layer.wkbType(), wkb_type) return layer def test_check_validity(self): """Test that the output invalid contains the error reason""" polygon_layer = self._make_layer('Polygon') self.assertTrue(polygon_layer.startEditing()) f = QgsFeature(polygon_layer.fields()) f.setAttributes([1]) # Flake! f.setGeometry(QgsGeometry.fromWkt( 'POLYGON ((0 0, 2 2, 0 2, 2 0, 0 0))')) self.assertTrue(f.isValid()) f2 = QgsFeature(polygon_layer.fields()) f2.setAttributes([1]) f2.setGeometry(QgsGeometry.fromWkt( 'POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))')) self.assertTrue(f2.isValid()) self.assertTrue(polygon_layer.addFeatures([f, f2])) polygon_layer.commitChanges() polygon_layer.rollBack() self.assertEqual(polygon_layer.featureCount(), 2) QgsProject.instance().addMapLayers([polygon_layer]) alg = self.registry.createAlgorithmById('qgis:checkvalidity') context = QgsProcessingContext() context.setProject(QgsProject.instance()) feedback = ConsoleFeedBack() self.assertIsNotNone(alg) parameters = {} parameters['INPUT_LAYER'] = polygon_layer.id() parameters['VALID_OUTPUT'] = 'memory:' parameters['INVALID_OUTPUT'] = 'memory:' parameters['ERROR_OUTPUT'] = 'memory:' # QGIS method parameters['METHOD'] = 1 ok, results = execute( alg, parameters, context=context, feedback=feedback) self.assertTrue(ok) invalid_layer = QgsProcessingUtils.mapLayerFromString( results['INVALID_OUTPUT'], context) self.assertEqual(invalid_layer.fields().names()[-1], '_errors') self.assertEqual(invalid_layer.featureCount(), 1) f = next(invalid_layer.getFeatures()) self.assertEqual(f.attributes(), [ 1, 'segments 0 and 2 of line 0 intersect at 1, 1']) # GEOS method parameters['METHOD'] = 2 ok, results = execute( alg, parameters, context=context, feedback=feedback) self.assertTrue(ok) invalid_layer = QgsProcessingUtils.mapLayerFromString( results['INVALID_OUTPUT'], context) self.assertEqual(invalid_layer.fields().names()[-1], '_errors') self.assertEqual(invalid_layer.featureCount(), 1) f = next(invalid_layer.getFeatures()) self.assertEqual(f.attributes(), [1, 'Self-intersection']) if __name__ == '__main__': unittest.main()