Skip to content

Commit 9b9d49a

Browse files
committed
Add unit tests for deferred layer refresh
QgsMapCanvas test is rather messy, but I can't find anyway to avoid showing the canvas in order to get a predictable result
1 parent 04d392b commit 9b9d49a

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ ADD_PYTHON_TEST(PyQgsGraduatedSymbolRenderer test_qgsgraduatedsymbolrenderer.py)
6363
ADD_PYTHON_TEST(PyQgsInterval test_qgsinterval.py)
6464
ADD_PYTHON_TEST(PyQgsJSONUtils test_qgsjsonutils.py)
6565
ADD_PYTHON_TEST(PyQgsLineSymbolLayers test_qgslinesymbollayers.py)
66+
ADD_PYTHON_TEST(PyQgsMapCanvas test_qgsmapcanvas.py)
6667
ADD_PYTHON_TEST(PyQgsMapCanvasAnnotationItem test_qgsmapcanvasannotationitem.py)
6768
ADD_PYTHON_TEST(PyQgsMapLayerModel test_qgsmaplayermodel.py)
6869
ADD_PYTHON_TEST(PyQgsMapRenderer test_qgsmaprenderer.py)

tests/src/python/test_qgsmapcanvas.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for QgsMapCanvas
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = 'Nyall Dawson'
10+
__date__ = '24/1/2017'
11+
__copyright__ = 'Copyright 2017, The QGIS Project'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
import qgis # NOQA
16+
17+
from qgis.core import (QgsMapSettings,
18+
QgsCoordinateReferenceSystem,
19+
QgsRectangle,
20+
QgsVectorLayer,
21+
QgsFeature,
22+
QgsGeometry,
23+
QgsMultiRenderChecker,
24+
QgsApplication)
25+
from qgis.gui import (QgsMapCanvas)
26+
27+
from qgis.PyQt.QtCore import (Qt,
28+
QDir)
29+
import time
30+
from qgis.testing import start_app, unittest
31+
32+
app = start_app()
33+
34+
35+
class TestQgsMapCanvas(unittest.TestCase):
36+
37+
def setUp(self):
38+
self.report = "<h1>Python QgsMapCanvas Tests</h1>\n"
39+
40+
def tearDown(self):
41+
report_file_path = "%s/qgistest.html" % QDir.tempPath()
42+
with open(report_file_path, 'a') as report_file:
43+
report_file.write(self.report)
44+
45+
def testDeferredUpdate(self):
46+
""" test that map canvas doesn't auto refresh on deferred layer update """
47+
canvas = QgsMapCanvas()
48+
canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326))
49+
canvas.setFrameStyle(0)
50+
canvas.resize(600, 400)
51+
self.assertEqual(canvas.width(), 600)
52+
self.assertEqual(canvas.height(), 400)
53+
54+
layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string",
55+
"layer", "memory")
56+
57+
canvas.setLayers([layer])
58+
canvas.setExtent(QgsRectangle(10, 30, 20, 35))
59+
canvas.show()
60+
61+
# need to wait until first redraw can occur (note that we first need to wait till drawing starts!)
62+
while not canvas.isDrawing():
63+
app.processEvents()
64+
while canvas.isDrawing():
65+
app.processEvents()
66+
67+
self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas))
68+
69+
# add polygon to layer
70+
f = QgsFeature()
71+
f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 25, 25, 45)))
72+
self.assertTrue(layer.dataProvider().addFeatures([f]))
73+
74+
# deferred update - so expect that canvas will not been refreshed
75+
layer.triggerRepaint(True)
76+
timeout = time.time() + 0.1
77+
while time.time() < timeout:
78+
# messy, but only way to check that canvas redraw doesn't occur
79+
self.assertFalse(canvas.isDrawing())
80+
# canvas should still be empty
81+
self.assertTrue(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas))
82+
83+
# refresh canvas
84+
canvas.refresh()
85+
while not canvas.isDrawing():
86+
app.processEvents()
87+
while canvas.isDrawing():
88+
app.processEvents()
89+
90+
# now we expect the canvas check to fail (since they'll be a new polygon rendered over it)
91+
self.assertFalse(self.canvasImageCheck('empty_canvas', 'empty_canvas', canvas))
92+
93+
def canvasImageCheck(self, name, reference_image, canvas):
94+
self.report += "<h2>Render {}</h2>\n".format(name)
95+
temp_dir = QDir.tempPath() + '/'
96+
file_name = temp_dir + 'mapcanvas_' + name + ".png"
97+
print(file_name)
98+
canvas.saveAsImage(file_name)
99+
checker = QgsMultiRenderChecker()
100+
checker.setControlPathPrefix("mapcanvas")
101+
checker.setControlName("expected_" + reference_image)
102+
checker.setRenderedImage(file_name)
103+
checker.setColorTolerance(2)
104+
result = checker.runTest(name, 20)
105+
self.report += checker.report()
106+
print((self.report))
107+
return result
108+
109+
110+
if __name__ == '__main__':
111+
unittest.main()

tests/src/python/test_qgsmaprenderercache.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ def testRequestRepaintSimple(self):
116116
self.assertFalse(cache.hasCacheImage('xxx'))
117117
QgsProject.instance().removeMapLayer(layer.id())
118118

119+
# test that cache is also cleared on deferred update
120+
layer = QgsVectorLayer("Point?field=fldtxt:string",
121+
"layer", "memory")
122+
cache.setCacheImage('xxx', im, [layer])
123+
layer.triggerRepaint(True)
124+
self.assertFalse(cache.hasCacheImage('xxx'))
125+
119126
def testRequestRepaintMultiple(self):
120127
""" test requesting repaint with multiple dependent layers """
121128
layer1 = QgsVectorLayer("Point?field=fldtxt:string",
Loading

0 commit comments

Comments
 (0)