QGIS 플러그인에 대한 자동화 된 테스트를 작성하고 있습니까?


16

파이썬으로 작성된 QGIS 플러그인에 대한 자동 테스트 작성에 대한 조언을 찾고 있습니다.

PyUnit ( unittest모듈)을 사용하여 과거에 Python 스크립트에 대한 테스트를 작성 했지만 GUI가있는 응용 프로그램에는 테스트를 수행하지 않았습니다. PyQt4.QTest를 사용하여 Qt 위젯에서 단위 테스트를 수행하는 방법을 설명하는 페이지를 찾았 지만 ( http://www.voom.net/pyqt-qtest-example ) 어떻게 사용할 수 있는지 고심하고 있습니다. QGIS 내에서 실행되도록 설계된 위젯이 있습니다.

PyQGIS 문서 의 "테스트"섹션 은 특히 ​​없습니다.

내가 지금까지 가지고있는 것은 :

  • 데이터의 실제 처리를 격리 된 모듈 또는 함수로 유지하고 이에 대한 단위 테스트를 작성하십시오.
  • QTest를 사용하여 UI의 기본 테스트를 수행하십시오.
  • QGIS 내에서 플러그인을 사용할 때 모두 함께 유지되도록기도하십시오.

더 좋은 방법이 있습니까?

답변:


11

QGIS 플러그인 테스트 기능 (특히 OP가 강조하는 QGIS 환경 내 통합 테스트 문제)이 최근 크게 개선되었습니다. 따라서이 업데이트가 최신 독자뿐만 아니라 OP에도 도움이 되길 바랍니다.

Boundless 는 2016 년 7 월 QGIS 플러그인 테스트 자동화에 대해 진지한 사용자를 위해 반드시 읽어야 할 기사를 게시했습니다. Python 플러그인을위한 QGIS Continuous Integration 테스트 환경 . 여기에는 이들이 사용하는 접근 방식과 도구가 설명되어 있으며 모두 오픈 소스입니다. 주요 측면은 다음과 같습니다.

  • QGIS 환경 내 에서 테스트를 자동화 할 수있는 특수한 QGIS 플러그인 테스터
  • 컨테이너 기반 환경에서 다양한 QGIS 버전 / 구성에 대해 테스트 할 수있는 docker QGIS 이미지 사용
  • 특별한 고정 표시기의 QGIS 이미지 QGIS 자체를 테스트하기 위해 사용되는,하지만 어느 - 호출하여이 qgis_testrunner.sh플러그인에 단위 테스트를 실행하는 데 사용할 수 있습니다
  • 지속적인 통합을 위해 Travis CI 를 사용합니다. 즉 전체 테스트 스위트는 새로운 코드 커밋마다 실행됩니다.

Travis CI / docker에 익숙하다면 비교적 쉽게 설정할 수 있어야합니다. 다음 4 단계를 설명하고 이러한 방식으로 설정된 자체 플러그인의 2 가지 예를 제공합니다.

  1. QGIS 테스트 환경에서 Docker 이미지를 가져 와서 실행하십시오.
  2. qgis_setup.sh NameOfYourPlugin을 실행하여 플러그인을 설치하고 테스트 실행자를위한 QGIS를 준비하십시오.
  3. 선택적으로 플러그인 빌드에 필요한 모든 작업을 수행
  4. Docker 내부에서 테스트 러너를 실행하여 qgis_testrunner.sh

당신은 모범 사례를 요청했습니다 & 오늘 기준으로 나는 분명히 이것을 고려할 것입니다. QGIS 문서는 여전히 플러그인 테스트에 대한 전용 섹션을 가지고 있지 않지만 (이것은 곧 바뀔 것으로 예상됩니다) "모든 것이 함께 유지되도록기도하십시오"접근 방식이 더 이상 유일한 옵션은 아닙니다.


4
무한은 더 이상 없습니다. 그 내용을 저장 한 사람이 있습니까?
— 페드로 마르고

8

독립 실행 형 Python 응용 프로그램에unittest 로드 된 Python 플러그인을 테스트하는 데 사용할 수있는 것 같습니다 .

qgis.core.iface는 독립형 응용 프로그램에서 사용할 수 없으므로 주어진 인수를 허용하고 다른 작업을 수행하지 않는 함수를 반환하는 더미 인스턴스를 작성했습니다. 즉, 같은 호출은 self.iface.addToolBarIcon(self.action)오류를 발생시키지 않습니다.

아래 예제는 plugin을로드합니다 myplugin. 여기에는 맵 레이어 레지스트리에서 가져온 레이어 이름이있는 드롭 다운 메뉴가 있습니다. 테스트는 메뉴가 올바르게 채워져 있고 상호 작용할 수 있는지 확인합니다. 이것이 플러그인을로드하는 가장 좋은 방법인지 확실하지 않지만 작동하는 것 같습니다.

myplugin 위젯

#!/usr/bin/env python

import unittest

import os
import sys

# configure python to play nicely with qgis
osgeo4w_root = r'C:/OSGeo4W'
os.environ['PATH'] = '{}/bin{}{}'.format(osgeo4w_root, os.pathsep, os.environ['PATH'])
sys.path.insert(0, '{}/apps/qgis/python'.format(osgeo4w_root))
sys.path.insert(1, '{}/apps/python27/lib/site-packages'.format(osgeo4w_root))

# import Qt
from PyQt4 import QtCore, QtGui, QtTest
from PyQt4.QtCore import Qt

# import PyQGIS
from qgis.core import *
from qgis.gui import *

# disable debug messages
os.environ['QGIS_DEBUG'] = '-1'

def setUpModule():
    # load qgis providers
    QgsApplication.setPrefixPath('{}/apps/qgis'.format(osgeo4w_root), True)
    QgsApplication.initQgis()

    globals()['shapefile_path'] = 'D:/MasterMap.shp'

# FIXME: this seems to throw errors
#def tearDownModule():
#    QgsApplication.exitQgis()

# dummy instance to replace qgis.utils.iface
class QgisInterfaceDummy(object):
    def __getattr__(self, name):
        # return an function that accepts any arguments and does nothing
        def dummy(*args, **kwargs):
            return None
        return dummy

class ExamplePluginTest(unittest.TestCase):
    def setUp(self):
        # create a new application instance
        self.app = app = QtGui.QApplication(sys.argv)

        # create a map canvas widget
        self.canvas = canvas = QgsMapCanvas()
        canvas.setCanvasColor(QtGui.QColor('white'))
        canvas.enableAntiAliasing(True)

        # load a shapefile
        layer = QgsVectorLayer(shapefile_path, 'MasterMap', 'ogr')

        # add the layer to the canvas and zoom to it
        QgsMapLayerRegistry.instance().addMapLayer(layer)
        canvas.setLayerSet([QgsMapCanvasLayer(layer)])
        canvas.setExtent(layer.extent())

        # display the map canvas widget
        #canvas.show()

        iface = QgisInterfaceDummy()

        # import the plugin to be tested
        import myplugin
        self.plugin = myplugin.classFactory(iface)
        self.plugin.initGui()
        self.dlg = self.plugin.dlg
        #self.dlg.show()

    def test_populated(self):
        '''Are the combo boxes populated correctly?'''
        self.assertEqual(self.dlg.ui.comboBox_raster.currentText(), '')
        self.assertEqual(self.dlg.ui.comboBox_vector.currentText(), 'MasterMap')
        self.assertEqual(self.dlg.ui.comboBox_all1.currentText(), '')
        self.dlg.ui.comboBox_all1.setCurrentIndex(1)
        self.assertEqual(self.dlg.ui.comboBox_all1.currentText(), 'MasterMap')

    def test_dlg_name(self):
        self.assertEqual(self.dlg.windowTitle(), 'Testing')

    def test_click_widget(self):
        '''The OK button should close the dialog'''
        self.dlg.show()
        self.assertEqual(self.dlg.isVisible(), True)
        okWidget = self.dlg.ui.buttonBox.button(self.dlg.ui.buttonBox.Ok)
        QtTest.QTest.mouseClick(okWidget, Qt.LeftButton)
        self.assertEqual(self.dlg.isVisible(), False)

    def tearDown(self):
        self.plugin.unload()
        del(self.plugin)
        del(self.app) # do not forget this

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

4
나는이 답변에 기초한 기사를 여기에 썼습니다
— Snorfalorpagus

3

또한 Qummy 플러그인을 독립형으로 테스트 할 수있는 DummyInterface도 함께 제공했습니다. Snorfalorpagus 블로그를 읽은 후 여기 에서 내 답변을 확인 하십시오 .

실생활 예제를 찾으려면, 내가 시험 (ED) QGIS - 플러그인에서이 GitHub의 프로젝트를 방문하는 방법에 https://github.com/UdK-VPT/Open_eQuarter/tree/master/mole을 과에보고가 테스트를 - 꾸러미.


-1

QTest 및 unittest를 사용하여 PyQt GUI 테스트 http://www.voom.net/pyqt-qtest-example


1
그것은 질문에 링크 된 "이 페이지"입니다 (물론 명확하지는 않습니다). 내 문제는 QGIS의 레이어로 채워진 콤보 상자와 같은 항목으로 실행되도록 설계된 인터페이스를 어떻게 테스트합니까?
— Snorfalorpagus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.