Skip to content

Commit

Permalink
Add some unit tests for QgsExpressionBuilderWidget
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 30, 2017
1 parent 878ee5c commit e79bf3f
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 0 deletions.
8 changes: 8 additions & 0 deletions python/gui/qgsexpressionbuilderwidget.sip
Expand Up @@ -236,6 +236,14 @@ Sets the expression string for the widget
Update the list of function files found at the given path
%End

QStandardItemModel *model();
%Docstring
Returns a pointer to the dialog's function item model.
This method is exposed for testing purposes only - it should not be used to modify the model.
.. versionadded:: 3.0
:rtype: QStandardItemModel
%End

public slots:

void loadSampleValues();
Expand Down
5 changes: 5 additions & 0 deletions src/gui/qgsexpressionbuilderwidget.cpp
Expand Up @@ -657,6 +657,11 @@ QString QgsExpressionBuilderWidget::formatLayerHelp( const QgsMapLayer *layer )
return text;
}

QStandardItemModel *QgsExpressionBuilderWidget::model()
{
return mModel;
}

void QgsExpressionBuilderWidget::showEvent( QShowEvent *e )
{
QWidget::showEvent( e );
Expand Down
7 changes: 7 additions & 0 deletions src/gui/qgsexpressionbuilderwidget.h
Expand Up @@ -226,6 +226,13 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
*/
void updateFunctionFileList( const QString &path );

/**
* Returns a pointer to the dialog's function item model.
* This method is exposed for testing purposes only - it should not be used to modify the model.
* \since QGIS 3.0
*/
QStandardItemModel *model();

public slots:

/**
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -47,6 +47,7 @@ ADD_PYTHON_TEST(PyQgsDistanceArea test_qgsdistancearea.py)
ADD_PYTHON_TEST(PyQgsEditWidgets test_qgseditwidgets.py)
ADD_PYTHON_TEST(PyQgsEllipsoidUtils test_qgsellipsoidutils.py)
ADD_PYTHON_TEST(PyQgsExpression test_qgsexpression.py)
ADD_PYTHON_TEST(PyQgsExpressionBuilderWidget test_qgsexpressionbuilderwidget.py)
ADD_PYTHON_TEST(PyQgsExpressionLineEdit test_qgsexpressionlineedit.py)
ADD_PYTHON_TEST(PyQgsExtentGroupBox test_qgsextentgroupbox.py)
ADD_PYTHON_TEST(PyQgsFeature test_qgsfeature.py)
Expand Down
158 changes: 158 additions & 0 deletions tests/src/python/test_qgsexpressionbuilderwidget.py
@@ -0,0 +1,158 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsExpressionBuilderWidget
.. 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__ = 'Nyall Dawson'
__date__ = '30/07/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

from qgis.PyQt.QtCore import Qt
from qgis.testing import start_app, unittest
from qgis.gui import QgsExpressionBuilderWidget
from qgis.core import (QgsExpressionContext,
QgsExpressionContextScope,
QgsProject,
QgsVectorLayer,
QgsRelation,
QgsFeature,
QgsGeometry)
start_app()


def createReferencingLayer():
layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer",
"referencinglayer", "memory")
pr = layer.dataProvider()
f1 = QgsFeature()
f1.setFields(layer.pendingFields())
f1.setAttributes(["test1", 123])
f2 = QgsFeature()
f2.setFields(layer.pendingFields())
f2.setAttributes(["test2", 123])
f3 = QgsFeature()
f3.setFields(layer.pendingFields())
f3.setAttributes(["foobar'bar", 124])
assert pr.addFeatures([f1, f2, f3])
return layer


def createReferencedLayer():
layer = QgsVectorLayer(
"Point?field=x:string&field=y:integer&field=z:integer",
"referencedlayer", "memory")
pr = layer.dataProvider()
f1 = QgsFeature()
f1.setFields(layer.pendingFields())
f1.setAttributes(["foo", 123, 321])
f2 = QgsFeature()
f2.setFields(layer.pendingFields())
f2.setAttributes(["bar", 456, 654])
f3 = QgsFeature()
f3.setFields(layer.pendingFields())
f3.setAttributes(["foobar'bar", 789, 554])
assert pr.addFeatures([f1, f2, f3])
return layer


class TestQgsExpressionBuilderWidget(unittest.TestCase):

def setUp(self):
self.referencedLayer = createReferencedLayer()
self.referencingLayer = createReferencingLayer()
QgsProject.instance().addMapLayers([self.referencedLayer, self.referencingLayer])

def testFunctionPresent(self):
""" check through widget model to ensure it is initially populated with functions """
w = QgsExpressionBuilderWidget()
m = w.model()
# check that some standard expression functions are shown
items = m.findItems('lower', Qt.MatchRecursive)
self.assertEqual(len(items), 1)
items = m.findItems('upper', Qt.MatchRecursive)
self.assertEqual(len(items), 1)
items = m.findItems('asdasdasda#$@#$', Qt.MatchRecursive)
self.assertEqual(len(items), 0)

def testVariables(self):
""" check through widget model to ensure it is populated with variables """
w = QgsExpressionBuilderWidget()
m = w.model()

s = QgsExpressionContextScope()
s.setVariable('my_var1', 'x')
s.setVariable('my_var2', 'y')
c = QgsExpressionContext()
c.appendScope(s)

# check that variables are added when setting context
w.setExpressionContext(c)
items = m.findItems('my_var1', Qt.MatchRecursive)
self.assertEqual(len(items), 1)
items = m.findItems('my_var2', Qt.MatchRecursive)
self.assertEqual(len(items), 1)
items = m.findItems('not_my_var', Qt.MatchRecursive)
self.assertEqual(len(items), 0)
# double check that functions are still only there once
items = m.findItems('lower', Qt.MatchRecursive)
self.assertEqual(len(items), 1)
items = m.findItems('upper', Qt.MatchRecursive)
self.assertEqual(len(items), 1)

def testLayers(self):
""" check that layers are shown in widget model"""
p = QgsProject.instance()
layer = QgsVectorLayer("Point", "layer1", "memory")
layer2 = QgsVectorLayer("Point", "layer2", "memory")
p.addMapLayers([layer, layer2])

w = QgsExpressionBuilderWidget()
m = w.model()

# check that layers are shown
items = m.findItems('layer1', Qt.MatchRecursive)
self.assertEqual(len(items), 1)
items = m.findItems('layer2', Qt.MatchRecursive)
self.assertEqual(len(items), 1)

def testRelations(self):
""" check that layers are shown in widget model"""
p = QgsProject.instance()

# not valid, but doesn't matter for test....
rel = QgsRelation()
rel.setId('rel1')
rel.setName('Relation Number One')
rel.setReferencingLayer(self.referencingLayer.id())
rel.setReferencedLayer(self.referencedLayer.id())
rel.addFieldPair('foreignkey', 'y')

rel2 = QgsRelation()
rel2.setId('rel2')
rel2.setName('Relation Number Two')
rel2.setReferencingLayer(self.referencingLayer.id())
rel2.setReferencedLayer(self.referencedLayer.id())
rel2.addFieldPair('foreignkey', 'y')

p.relationManager().addRelation(rel)
p.relationManager().addRelation(rel2)

w = QgsExpressionBuilderWidget()
m = w.model()

# check that relations are shown
items = m.findItems('Relation Number One', Qt.MatchRecursive)
self.assertEqual(len(items), 1)
items = m.findItems('Relation Number Two', Qt.MatchRecursive)
self.assertEqual(len(items), 1)


if __name__ == '__main__':
unittest.main()

0 comments on commit e79bf3f

Please sign in to comment.