Add tests

This commit is contained in:
Blottiere Paul 2017-09-07 11:33:54 +02:00
parent 3f8ae8b225
commit 3d7ac65764
3 changed files with 393 additions and 0 deletions

View File

@ -186,6 +186,7 @@ ADD_PYTHON_TEST(PyQgsZipUtils test_qgsziputils.py)
ADD_PYTHON_TEST(PyQgsSourceSelectProvider test_qgssourceselectprovider.py)
ADD_PYTHON_TEST(PyQgsAuthManagerProxy test_authmanager_proxy.py)
ADD_PYTHON_TEST(PyQgsAuthSettingsWidget test_authsettingswidget.py)
ADD_PYTHON_TEST(PyQgsAuxiliaryStorage test_qgsauxiliarystorage.py)
IF (NOT WIN32)
ADD_PYTHON_TEST(PyQgsLogger test_qgslogger.py)

View File

@ -0,0 +1,390 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for Auxiliary Storage.
.. 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__ = 'Paul Blottiere'
__date__ = '06/09/2017'
__copyright__ = 'Copyright 2017, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import qgis # NOQA
import os
from qgis.PyQt.QtCore import QTemporaryFile
from qgis.core import (QgsAuxiliaryStorage,
QgsAuxiliaryLayer,
QgsVectorLayer,
QgsFeature,
QgsGeometry,
QgsPropertyDefinition,
QgsProject,
QgsFeatureRequest,
QgsPalLayerSettings,
QgsSymbolLayer,
QgsVectorLayerSimpleLabeling,
NULL)
from qgis.testing import start_app, unittest
from utilities import unitTestDataPath, writeShape
start_app()
def tmpPath():
f = QTemporaryFile()
f.open()
f.close()
os.remove(f.fileName())
return f.fileName()
def createLayer():
vl = QgsVectorLayer(
'Point?crs=epsg:4326&field=pk:integer&field=cnt:integer&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk', 'test', 'memory')
assert (vl.isValid())
f1 = QgsFeature()
f1.setAttributes([5, -200, NULL, 'NuLl', '5'])
f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)'))
f2 = QgsFeature()
f2.setAttributes([3, 300, 'Pear', 'PEaR', '3'])
f3 = QgsFeature()
f3.setAttributes([1, 100, 'Orange', 'oranGe', '1'])
f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)'))
f4 = QgsFeature()
f4.setAttributes([2, 200, 'Apple', 'Apple', '2'])
f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)'))
f5 = QgsFeature()
f5.setAttributes([4, 400, 'Honey', 'Honey', '4'])
f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)'))
vl.dataProvider().addFeatures([f1, f2, f3, f4, f5])
return vl
class TestQgsAuxiliaryStorage(unittest.TestCase):
def testCreateSaveOpenStorageWithString(self):
# Empty string in copy mode. A new database is created in a temporary
# file.
s0 = QgsAuxiliaryStorage()
self.assertTrue(s0.isValid())
# saveAs should be used instead of save in case of an empty string
# given to the constructor of QgsAuxiliaryStorage
self.assertEqual(s0.fileName(), "")
self.assertFalse(s0.save())
# Create a new auxiliary layer with 'pk' as key
vl0 = createLayer()
pkf = vl0.fields().field(vl0.fields().indexOf('pk'))
al0 = s0.createAuxiliaryLayer(pkf, vl0)
self.assertTrue(al0.isValid())
# Test the auxiliary key
key = al0.joinInfo().targetFieldName()
self.assertEqual(key, 'pk')
# Add a field in auxiliary layer
p = QgsPropertyDefinition('propName', QgsPropertyDefinition.DataTypeNumeric, '', '', 'user')
self.assertTrue(al0.addAuxiliaryField(p))
# saveAs without saving the auxiliary layer, the auxiliary field is lost
f = tmpPath()
self.assertTrue(s0.saveAs(f))
# Open the previous database.
s1 = QgsAuxiliaryStorage(f)
self.assertTrue(s1.isValid())
# Load the auxiliary layer from auxiliary storage
self.assertTrue(vl0.loadAuxiliaryLayer(s1, key))
# As the vl0 has not been saved before saving the storage, there
# shouldn't have auxiliary fields
self.assertEqual(len(vl0.auxiliaryLayer().auxiliaryFields()), 0)
# Save the layer before saving the storage
self.assertTrue(al0.save())
self.assertTrue(s0.saveAs(f))
# Open the previous database.
s2 = QgsAuxiliaryStorage(f)
self.assertTrue(s2.isValid())
# Load the auxiliary layer from auxiliary storage
self.assertTrue(vl0.loadAuxiliaryLayer(s2, key))
# As the vl0 has been saved before saving the storage, there
# should have 1 auxiliary field
self.assertEqual(len(vl0.auxiliaryLayer().auxiliaryFields()), 1)
# save is available on s2
self.assertTrue(s2.save())
def testCreateSaveOpenStorageWithProject(self):
# New project without fileName
p = QgsProject()
# Create storage
s0 = QgsAuxiliaryStorage(p)
self.assertTrue(s0.isValid())
# saveAs should be used instead of save in case of an empty string
# given to the constructor of QgsAuxiliaryStorage
self.assertEqual(s0.fileName(), "")
self.assertFalse(s0.save())
# saveAs
f = tmpPath()
self.assertTrue(s0.saveAs(f))
def testProjectStorage(self):
# New project without fileName
p0 = QgsProject()
self.assertTrue(p0.auxiliaryStorage().isValid())
# Create new layers with key otherwise auxiliary layers are not
# automacially created when added in project
vl0 = createLayer()
vl0Shp = writeShape(vl0, 'vl0.shp')
vl1 = createLayer()
vl1Shp = writeShape(vl1, 'vl1.shp')
vl0 = QgsVectorLayer(vl0Shp, 'points', 'ogr')
self.assertTrue(vl0.isValid())
vl1 = QgsVectorLayer(vl1Shp, 'points', 'ogr')
self.assertTrue(vl1.isValid())
# Add layers to project and check underlying auxiliary layers
p0.addMapLayers([vl0, vl1])
self.assertTrue(vl0.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'pk'))
self.assertTrue(vl1.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'num_char'))
al0 = vl0.auxiliaryLayer()
al1 = vl1.auxiliaryLayer()
self.assertEqual(al0.joinInfo().targetFieldName(), 'pk')
self.assertEqual(al1.joinInfo().targetFieldName(), 'num_char')
# Add a field in auxiliary layers
pdef0 = QgsPropertyDefinition('propname', QgsPropertyDefinition.DataTypeNumeric, '', '', 'ut')
self.assertTrue(al0.addAuxiliaryField(pdef0))
pdef1 = QgsPropertyDefinition('propname1', QgsPropertyDefinition.DataTypeString, '', '', 'ut')
self.assertTrue(al1.addAuxiliaryField(pdef1))
# Check auxiliary fields names
af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, False)
self.assertEqual(af0Name, 'ut_propname')
af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, False)
self.assertEqual(af1Name, 'ut_propname1')
# Set value for auxiliary fields
req = QgsFeatureRequest().setFilterExpression("name = 'Honey'")
f = QgsFeature()
vl0.getFeatures(req).nextFeature(f)
self.assertTrue(f.isValid())
af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, True)
index0 = vl0.fields().indexOf(af0Name)
vl0.changeAttributeValue(f.id(), index0, 333)
req = QgsFeatureRequest().setFilterExpression("name = 'Apple'")
f = QgsFeature()
vl1.getFeatures(req).nextFeature(f)
self.assertTrue(f.isValid())
af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, True)
index1 = vl1.fields().indexOf(af1Name)
vl1.changeAttributeValue(f.id(), index0, 'myvalue')
req = QgsFeatureRequest().setFilterExpression("name = 'Orange'")
f = QgsFeature()
vl1.getFeatures(req).nextFeature(f)
self.assertTrue(f.isValid())
vl1.changeAttributeValue(f.id(), index0, 'myvalue1')
# Save the project in a zip file
f = tmpPath() + '.qgz'
p0.write(f)
# Open the zip file with embedded auxiliary storage
p1 = QgsProject()
p1.read(f)
# Check that auxiliary fields are well loaded in layers
self.assertEqual(len(p1.mapLayers().values()), 2)
for vl in p1.mapLayers().values():
al = vl.auxiliaryLayer()
self.assertEqual(len(al.auxiliaryFields()), 1)
af = al.auxiliaryFields()[0]
afPropDef = QgsAuxiliaryLayer.propertyDefinitionFromField(af)
self.assertEqual(afPropDef.origin(), 'ut')
if vl.auxiliaryLayer().joinInfo().targetFieldName() == 'pk':
self.assertEqual(afPropDef.name(), 'propname')
self.assertEqual(al.featureCount(), 1)
req = QgsFeatureRequest().setFilterExpression("name = 'Honey'")
f = QgsFeature()
vl.getFeatures(req).nextFeature(f)
self.assertTrue(f.isValid())
self.assertEqual(f.attributes()[index0], 333.0)
else: # num_char
self.assertEqual(al.featureCount(), 2)
self.assertEqual(afPropDef.name(), 'propname1')
req = QgsFeatureRequest().setFilterExpression("name = 'Apple'")
f = QgsFeature()
vl.getFeatures(req).nextFeature(f)
self.assertTrue(f.isValid())
self.assertEqual(f.attributes()[index1], 'myvalue')
req = QgsFeatureRequest().setFilterExpression("name = 'Orange'")
f = QgsFeature()
vl.getFeatures(req).nextFeature(f)
self.assertTrue(f.isValid())
self.assertEqual(f.attributes()[index1], 'myvalue1')
def testAuxiliaryFieldWidgets(self):
# Init storage
s = QgsAuxiliaryStorage()
self.assertTrue(s.isValid())
# Create a new auxiliary layer with 'pk' as key
vl = createLayer()
pkf = vl.fields().field(vl.fields().indexOf('pk'))
al = s.createAuxiliaryLayer(pkf, vl)
self.assertTrue(al.isValid())
# Set the auxiliary layer to the vector layer
vl.setAuxiliaryLayer(al)
# Add a visible property
p = QgsPropertyDefinition('propName', QgsPropertyDefinition.DataTypeNumeric, '', '', 'user')
self.assertTrue(al.addAuxiliaryField(p))
index = al.indexOfPropertyDefinition(p)
self.assertFalse(al.isHiddenProperty(index))
afName = QgsAuxiliaryLayer.nameFromProperty(p, True)
index = vl.fields().indexOf(afName)
setup = vl.editorWidgetSetup(index)
self.assertEqual(setup.type(), '')
tested = False
for c in vl.attributeTableConfig().columns():
if c.name == afName:
self.assertFalse(c.hidden)
tested = True
break
self.assertTrue(tested)
# Add a hidden property
p = QgsPalLayerSettings.propertyDefinitions()[QgsPalLayerSettings.PositionX]
self.assertTrue(al.addAuxiliaryField(p))
index = al.indexOfPropertyDefinition(p)
self.assertTrue(al.isHiddenProperty(index))
afName = QgsAuxiliaryLayer.nameFromProperty(p, True)
index = vl.fields().indexOf(afName)
setup = vl.editorWidgetSetup(index)
self.assertEqual(setup.type(), 'Hidden')
tested = False
for c in vl.attributeTableConfig().columns():
if c.name == afName:
self.assertTrue(c.hidden)
tested = True
break
self.assertTrue(tested)
# Add a color property
p = QgsSymbolLayer.propertyDefinitions()[QgsSymbolLayer.PropertyFillColor]
self.assertTrue(al.addAuxiliaryField(p))
index = al.indexOfPropertyDefinition(p)
self.assertFalse(al.isHiddenProperty(index))
afName = QgsAuxiliaryLayer.nameFromProperty(p, True)
index = vl.fields().indexOf(afName)
setup = vl.editorWidgetSetup(index)
self.assertEqual(setup.type(), 'Color')
def testClear(self):
s = QgsAuxiliaryStorage()
self.assertTrue(s.isValid())
# Create a new auxiliary layer with 'pk' as key
vl = createLayer()
pkf = vl.fields().field(vl.fields().indexOf('pk'))
al = s.createAuxiliaryLayer(pkf, vl)
self.assertTrue(al.isValid())
vl.setAuxiliaryLayer(al)
# Add a field in auxiliary layer
p = QgsPropertyDefinition('myprop', QgsPropertyDefinition.DataTypeNumeric, '', '', 'me')
self.assertFalse(al.exists(p))
self.assertTrue(al.addAuxiliaryField(p))
self.assertTrue(al.exists(p))
# Count auxiliary features
self.assertEqual(al.featureCount(), 0)
# Set value for auxiliary fields
req = QgsFeatureRequest().setFilterExpression("name = 'Honey'")
f = QgsFeature()
vl.getFeatures(req).nextFeature(f)
self.assertTrue(f.isValid())
afName = QgsAuxiliaryLayer.nameFromProperty(p, True)
index = vl.fields().indexOf(afName)
vl.changeAttributeValue(f.id(), index, 333)
# Count auxiliary features
self.assertEqual(al.featureCount(), 1)
# Clear and count
al.clear()
self.assertEqual(al.featureCount(), 0)
def testCreateProperty(self):
s = QgsAuxiliaryStorage()
self.assertTrue(s.isValid())
# Create a new auxiliary layer with 'pk' as key
vl = createLayer()
pkf = vl.fields().field(vl.fields().indexOf('pk'))
al = s.createAuxiliaryLayer(pkf, vl)
self.assertTrue(al.isValid())
vl.setAuxiliaryLayer(al)
# Create a new labeling property on layer without labels
key = QgsPalLayerSettings.PositionX
index = QgsAuxiliaryLayer.createProperty(key, vl)
self.assertEqual(index, -1)
vl.setLabeling(QgsVectorLayerSimpleLabeling(QgsPalLayerSettings()))
index = QgsAuxiliaryLayer.createProperty(key, vl)
p = QgsPalLayerSettings.propertyDefinitions()[key]
afName = QgsAuxiliaryLayer.nameFromProperty(p, True)
afIndex = vl.fields().indexOf(afName)
self.assertEqual(index, afIndex)
if __name__ == '__main__':
unittest.main()

View File

@ -123,6 +123,8 @@ def writeShape(theMemoryLayer, theFileName):
mySkipAttributesFlag)
assert myResult == QgsVectorFileWriter.NoError, 'Writing shape failed, Error {} ({})'.format(myResult, myErrorMessage)
return myFileName
def doubleNear(a, b, tol=0.0000000001):
"""