我想对我们的小部件进行单元测试拖放。目前,我实例化了一个QDragEnterEvent,但是不建议在Qt文档上发出重大警告,因为它依赖于Qt库内部状态。事实上,我得到的段错误似乎是由于违反了此警告。
鉴于此前提,如何测试拖放行为?
答案 0 :(得分:5)
如果使用Unix我们可以使用QTest,但是为了获得跨平台解决方案,我们可以实施一个我们绕过Qt的解决方案。
虽然drag and drop的Qt文档说它不会阻止主事件循环,但仔细查看QDrag.exec
将会发现Windows不适用。
对QTest.mousePress
的调用导致测试阻塞,直到用户物理移动鼠标。
我在Linux中通过使用计时器安排鼠标移动和释放来解决这个问题:
def testDragAndDrop(self):
QtCore.QTimer.singleShot(100, self.dropIt)
QtTest.QTest.mousePress(dragFromWidget, QtCore.Qt.LeftButton)
# check for desired behaviour after drop
assert something
def dropIt(self):
QtTest.QTest.mouseMove(dropToWidget)
QtTest.QTest.mouseRelease(dropToWidget, QtCore.Qt.LeftButton, delay=15)
对于此解决方案,有必要在mouseRelease
调用中包含延迟,并在您的小部件上调用show
。
请注意,我已经在Fedora 20上使用pyqt4和Python 2.7验证了这一点
您可以使用PyUserInput包中的鼠标操作方法。将鼠标交互放在单独的线程中以避免锁定Qt主事件循环。我们可以这样做,因为我们在鼠标控制中根本没有使用Qt。确保您在要拖动的小部件上调用了show
。
from __future__ import division
import sys, time, threading
import numpy as np
from PyQt4 import QtGui, QtCore, QtTest
from pymouse import PyMouse
...
def mouseDrag(source, dest, rate=1000):
"""Simulate a mouse visible mouse drag from source to dest, rate is pixels/second"""
mouse = PyMouse()
mouse.press(*source)
# smooth move from source to dest
npoints = int(np.sqrt((dest[0]-source[0])**2 + (dest[1]-source[1])**2 ) / (rate/1000))
for i in range(npoints):
x = int(source[0] + ((dest[0]-source[0])/npoints)*i)
y = int(source[1] + ((dest[1]-source[1])/npoints)*i)
mouse.move(x,y)
time.sleep(0.001)
mouse.release(*dest)
def center(widget):
midpoint = QtCore.QPoint(widget.width()/2, widget.height()/2)
return widget.mapToGlobal(midpoint)
def testDragAndDrop(self):
# grab the center of the widgets
fromPos = center(dragFromWidget)
toPos = center(dropToWidget)
dragThread = threading.Thread(target=mouseDrag, args=((fromPos.x(),fromPos.y()), (toPos.x(), toPos.y())))
dragThread.start()
# cannot join, use non-blocking wait
while dragThread.is_alive():
QtTest.QTest.qWait(1000)
# check that the drop had the desired effect
assert dropToWidget.hasItemCount() > 0
注意我已经在Fedora和Windows 7上使用PyQt4和Python 2.7测试过它
答案 1 :(得分:1)
Haven没试过,但如果你的拖累和drop process是Qt internal(意思是,你从Qt小部件拖动到Qt小部件),QTest可能会有所帮助。
基本上做了一些事情:
QTest.mousePress(drag_widget, Qt.LeftButton) # simulate mouse press on whatever you want to drag
QTest.mouseMove(drop_widget) # move the mouse to the target - maybe this can be skipped
QTest.mouseRelease(drop_widget, Qt.LeftButton) # simulate mouse release where you want to drop
可以为所有功能提供更多位置信息(例如,单击小部件中的列表项),并使用可选的延迟来模拟人类用户。
不是可复制粘贴的答案,但也许它可以作为首发......