เขียนแบบทดสอบอัตโนมัติสำหรับปลั๊กอิน QGIS?


16

ฉันกำลังมองหาคำแนะนำในการเขียนการทดสอบอัตโนมัติสำหรับปลั๊กอิน QGIS ที่เขียนใน Python

ฉันได้เขียนการทดสอบสำหรับสคริปต์ Python ในอดีตโดยใช้ PyUnit ( unittestโมดูล) แต่ไม่เคยทำเช่นนั้นสำหรับแอปพลิเคชันที่มี GUI ฉันพบหน้าอธิบายวิธีใช้ PyQt4.QTest เพื่อทำการทดสอบหน่วยในวิดเจ็ต Qt ( http://www.voom.net/pyqt-qtest-example ) แต่ฉันพยายามดิ้นรนเพื่อดูว่าฉันสามารถใช้สิ่งนี้ได้อย่างไร ด้วยวิดเจ็ตที่ได้รับการออกแบบให้เรียกใช้จากภายใน QGIS

ส่วนที่เกี่ยวกับ "การทดสอบ" ในเอกสารประกอบ PyQGISนั้นไม่มีอยู่

สิ่งที่ฉันมีอยู่คือ:

  • เก็บการประมวลผลข้อมูลจริงในโมดูลหรือฟังก์ชั่นแยกและเขียนการทดสอบหน่วยสำหรับสิ่งเหล่านั้น
  • ทำการทดสอบพื้นฐานของ UI โดยใช้ QTest
  • โปรดอธิษฐานให้ทุกอย่างอยู่ด้วยกันเมื่อใช้ปลั๊กอินจากภายใน QGIS

มีวิธีที่ดีกว่า?

คำตอบ:


11

ความสามารถในการทดสอบปลั๊กอิน QGIS (โดยเฉพาะคำถามของการทดสอบการรวมภายในสภาพแวดล้อม QGIS เป็นไฮไลท์ OP) ได้ปรับปรุงข้อตกลงอย่างมากเมื่อเร็ว ๆ นี้ ฉันจึงหวังว่าการอัปเดตนี้จะช่วยให้ผู้อ่านร่วมสมัยและ OP

ไม่มีขอบเขตเผยแพร่บทความต้องอ่านในเดือนกรกฎาคม 2559 สำหรับทุกคนที่จริงจังเกี่ยวกับการทดสอบปลั๊กอิน QGIS โดยอัตโนมัติที่มีชื่อว่า; QGIS ต่อเนื่องบูรณาการการทดสอบสิ่งแวดล้อมหลามปลั๊กอิน มันอธิบายวิธีการและเครื่องมือที่ใช้ - ทั้งหมดเป็นโอเพ่นซอร์ส ประเด็นสำคัญคือ: -

  • เครื่องทดสอบปลั๊กอิน QGISพิเศษของพวกเขาซึ่งสามารถทำการทดสอบอัตโนมัติภายในสภาพแวดล้อม QGIS
  • การใช้งานของนักเทียบท่า QGIS ภาพที่ช่วยให้การทดสอบกับรุ่น QGIS ต่างๆ / การกำหนดค่าในสภาพแวดล้อมที่ภาชนะฐาน
  • ภาพพิเศษนักเทียบท่า QGISซึ่งจะใช้สำหรับการทดสอบ QGIS ตัวเอง แต่ที่ - โดยกล่าวอ้างqgis_testrunner.shสามารถใช้ในการเรียกใช้การทดสอบหน่วยปลั๊กอิน
  • การใช้Travis CIสำหรับการรวมอย่างต่อเนื่อง - เช่นชุดทดสอบเต็มรูปแบบจะทำงานด้วยรหัสใหม่ทุกการกระทำ

หากคุณคุ้นเคยกับ Travis CI / นักเทียบท่ามันควรจะตั้งค่าได้ง่าย พวกเขาอธิบาย 4 ขั้นตอนต่อไปนี้และให้ตัวอย่าง 2 ตัวอย่างของการตั้งค่าปลั๊กอินด้วยวิธีนี้

  1. ดึงอิมเมจ Docker ด้วยสภาพแวดล้อมการทดสอบ QGIS และเรียกใช้
  2. เรียกใช้ qgis_setup.sh NameOfYourPlugin เพื่อติดตั้งปลั๊กอินและเตรียม QGIS สำหรับนักวิ่งทดสอบ
  3. เลือกดำเนินการทั้งหมดที่จำเป็นในการสร้างปลั๊กอินของคุณ
  4. เรียกใช้ตัวทดสอบใน Docker เรียกใช้ qgis_testrunner.sh

คุณขอแนวปฏิบัติที่ดีที่สุดและ ณ วันนี้ฉันจะพิจารณาเรื่องนี้อย่างแน่นอน เอกสาร QGIS ยังไม่มีส่วนเฉพาะสำหรับการทดสอบปลั๊กอิน (ฉันคาดว่าจะมีการเปลี่ยนแปลงในไม่ช้า) แต่วิธีการ "อธิษฐานให้ทุกอย่างอยู่ด้วยกัน" ไม่ได้เป็นเพียงตัวเลือกเท่านั้น


4
ไม่มีที่สิ้นสุดไม่มีอีกแล้ว มีใครบันทึกเนื้อหานั้นบ้าง
Pedro Camargo

8

ลักษณะเช่นนี้เป็นไปได้ที่จะใช้unittestในการทดสอบหลามปลั๊กอินโหลดลงในแอปพลิเคหลามแบบสแตนด์อโลน

qgis.core.iface ไม่สามารถใช้งานได้จากแอปพลิเคชันแบบสแตนด์อโลนดังนั้นฉันจึงเขียนอินสแตนซ์จำลองที่ส่งกลับฟังก์ชันซึ่งจะยอมรับอาร์กิวเมนต์ที่กำหนดให้และไม่ทำอะไรเลย ซึ่งหมายความว่าการโทรอย่างself.iface.addToolBarIcon(self.action)ไม่ทำให้เกิดข้อผิดพลาด

ตัวอย่างด้านล่างโหลดปลั๊กอิน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
ฉันได้เขียนบทความตามคำตอบนี้ที่นี่: snorf.net/blog/2014/01/04/…
Snorfalorpagus

3

ฉันได้รวม DummyInterface เข้าด้วยกันซึ่งช่วยให้คุณทดสอบปลั๊กอิน QGIS แบบสแตนด์อโลน หลังจากที่ได้อ่านบล็อก Snorfalorpagus ตรวจสอบคำตอบของฉันที่นี่

เพื่อหาตัวอย่างในชีวิตจริงเกี่ยวกับวิธีที่ฉันทดสอบ (ed) QGIS-plugins เยี่ยมชมโครงการ Github นี้ที่https://github.com/UdK-VPT/Open_eQuarter/tree/master/moleและดูการทดสอบ - บรรจุภัณฑ์


-1

สิ่งนี้สามารถช่วยได้: ทดสอบ PyQt GUIs ด้วย QTest และ unittest http://www.voom.net/pyqt-qtest-example


1
นั่นคือ "หน้านี้" ที่เชื่อมโยงกับคำถาม (ยอมรับไม่ชัดเจนเกินไป) ปัญหาของฉันคือฉันจะทดสอบอินเทอร์เฟซที่ออกแบบมาเพื่อทำงานกับสิ่งต่าง ๆ เช่นกล่องคำสั่งผสมที่มีเลเยอร์ใน QGIS ได้อย่างไร
Snorfalorpagus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.