如何使用pytest-qt自动化鼠标拖动?
How to automate mouse drag using pytest-qt?
我有一个 pyqt window 可以在按下鼠标时跟踪鼠标移动。我正在尝试使用 pytest-qt 编写一个测试来自动执行此移动。
这是一个例子class:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QApplication
class Tracker(QDialog):
def __init__(self, parent=None):
super(Tracker, self).__init__(parent)
self.location = None
self.cur = QCursor()
layout = QVBoxLayout()
self.label = QLabel()
layout.addWidget(self.label)
self.setLayout(layout)
self.setModal(True)
self.showFullScreen()
def mouseReleaseEvent(self, e):
x = self.cur.pos().x()
y = self.cur.pos().y()
self.location = (x, y)
return super().mouseReleaseEvent(e)
def mouseMoveEvent(self, e):
x = self.cur.pos().x()
y = self.cur.pos().y()
self.label.setText(f'x: {x}, y: {y}')
return super().mouseMoveEvent(e)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Tracker()
sys.exit(app.exec_())
我想编写一个测试用例,打开 window 然后将鼠标向右拖动 100 像素并释放。
这是我尝试过的方法:
track = Tracker()
qtbot.mousePress(track, QtCore.Qt.LeftButton, pos=QPoint(300, 300))
qtbot.mouseMove(track, pos=QPoint(400, 300))
qtbot.mouseRelease(track, QtCore.Qt.LeftButton)
assert track.location == (400, 300)
我也试过使用 pyautogui:
track = Tracker()
x, y = pyautogui.position()
pyautogui.dragTo(x + 100, y, button='left')
assert track.location == (x + 100, y)
当运行测试时出现鼠标左键在拖动时没有按住。标签不会更新,位置属性不会改变。
- 使用 qtbot.mouseMove()
:
pytest-qt对QtTest进行了包装,即函数qtbot.mouseMove()与QTest::mouseMove()
. And this function has a bug that is reported QTBUG-5232相同,将在Qt6/PyQt6中修复,在注释中报告中有几种解决方法,即通过模拟 QMouseEvent 来替换该函数,该函数不会使光标移动,但如果它调用 mouseMoveEvent 方法,那么为了正常工作,您将不得不修改代码。
from PyQt5.QtWidgets import QApplication, QDialog, QLabel, QVBoxLayout
class Tracker(QDialog):
def __init__(self, parent=None):
super(Tracker, self).__init__(parent)
self.location = None
self.label = QLabel()
layout = QVBoxLayout(self)
layout.addWidget(self.label)
self.setModal(True)
self.showFullScreen()
def mouseReleaseEvent(self, e):
pos = self.mapToGlobal(e.pos())
self.location = pos.x(), pos.y()
return super().mouseReleaseEvent(e)
def mouseMoveEvent(self, e):
pos = self.mapToGlobal(e.pos())
self.label.setText(f"x: {pos.x()}, y: {pos.y()}")
return super().mouseMoveEvent(e)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = Tracker()
sys.exit(app.exec_())
def test_emulate_QMouseEvent(qtbot):
start_pos, end_pos = QtCore.QPoint(300, 300), QtCore.QPoint(400, 300)
track = Tracker()
def on_value_changed(value):
event = QtGui.QMouseEvent(
QtCore.QEvent.MouseMove,
value,
QtCore.Qt.NoButton,
QtCore.Qt.LeftButton,
QtCore.Qt.NoModifier,
)
QtCore.QCoreApplication.sendEvent(track, event)
animation = QtCore.QVariantAnimation(
startValue=start_pos, endValue=end_pos, duration=5000
)
qtbot.mousePress(track, QtCore.Qt.LeftButton, pos=QtCore.QPoint(300, 300))
animation.valueChanged.connect(on_value_changed)
with qtbot.waitSignal(animation.finished, timeout=10000):
animation.start()
qtbot.mouseRelease(track, QtCore.Qt.LeftButton)
track.location == (end_pos.x(), end_pos.y())
- 使用 pyautogui:
使用此方法无需进行任何更改。
def test_pyautogui(qtbot):
start_pos, end_pos = QtCore.QPoint(300, 300), QtCore.QPoint(400, 300)
track = Tracker()
qtbot.waitUntil(track.isVisible)
def on_value_changed(value):
pyautogui.dragTo(value.x(), value.y(), button="left")
animation = QtCore.QVariantAnimation(
startValue=start_pos, endValue=end_pos, duration=5000
)
pyautogui.moveTo(start_pos.x(), start_pos.y())
pyautogui.mouseDown(button="left")
animation.valueChanged.connect(on_value_changed)
with qtbot.waitSignal(animation.finished, timeout=10000):
animation.start()
track.location == (end_pos.x(), end_pos.y())
我有一个 pyqt window 可以在按下鼠标时跟踪鼠标移动。我正在尝试使用 pytest-qt 编写一个测试来自动执行此移动。
这是一个例子class:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QApplication
class Tracker(QDialog):
def __init__(self, parent=None):
super(Tracker, self).__init__(parent)
self.location = None
self.cur = QCursor()
layout = QVBoxLayout()
self.label = QLabel()
layout.addWidget(self.label)
self.setLayout(layout)
self.setModal(True)
self.showFullScreen()
def mouseReleaseEvent(self, e):
x = self.cur.pos().x()
y = self.cur.pos().y()
self.location = (x, y)
return super().mouseReleaseEvent(e)
def mouseMoveEvent(self, e):
x = self.cur.pos().x()
y = self.cur.pos().y()
self.label.setText(f'x: {x}, y: {y}')
return super().mouseMoveEvent(e)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Tracker()
sys.exit(app.exec_())
我想编写一个测试用例,打开 window 然后将鼠标向右拖动 100 像素并释放。
这是我尝试过的方法:
track = Tracker()
qtbot.mousePress(track, QtCore.Qt.LeftButton, pos=QPoint(300, 300))
qtbot.mouseMove(track, pos=QPoint(400, 300))
qtbot.mouseRelease(track, QtCore.Qt.LeftButton)
assert track.location == (400, 300)
我也试过使用 pyautogui:
track = Tracker()
x, y = pyautogui.position()
pyautogui.dragTo(x + 100, y, button='left')
assert track.location == (x + 100, y)
当运行测试时出现鼠标左键在拖动时没有按住。标签不会更新,位置属性不会改变。
- 使用 qtbot.mouseMove()
:
pytest-qt对QtTest进行了包装,即函数qtbot.mouseMove()与QTest::mouseMove()
. And this function has a bug that is reported QTBUG-5232相同,将在Qt6/PyQt6中修复,在注释中报告中有几种解决方法,即通过模拟 QMouseEvent 来替换该函数,该函数不会使光标移动,但如果它调用 mouseMoveEvent 方法,那么为了正常工作,您将不得不修改代码。
from PyQt5.QtWidgets import QApplication, QDialog, QLabel, QVBoxLayout
class Tracker(QDialog):
def __init__(self, parent=None):
super(Tracker, self).__init__(parent)
self.location = None
self.label = QLabel()
layout = QVBoxLayout(self)
layout.addWidget(self.label)
self.setModal(True)
self.showFullScreen()
def mouseReleaseEvent(self, e):
pos = self.mapToGlobal(e.pos())
self.location = pos.x(), pos.y()
return super().mouseReleaseEvent(e)
def mouseMoveEvent(self, e):
pos = self.mapToGlobal(e.pos())
self.label.setText(f"x: {pos.x()}, y: {pos.y()}")
return super().mouseMoveEvent(e)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = Tracker()
sys.exit(app.exec_())
def test_emulate_QMouseEvent(qtbot):
start_pos, end_pos = QtCore.QPoint(300, 300), QtCore.QPoint(400, 300)
track = Tracker()
def on_value_changed(value):
event = QtGui.QMouseEvent(
QtCore.QEvent.MouseMove,
value,
QtCore.Qt.NoButton,
QtCore.Qt.LeftButton,
QtCore.Qt.NoModifier,
)
QtCore.QCoreApplication.sendEvent(track, event)
animation = QtCore.QVariantAnimation(
startValue=start_pos, endValue=end_pos, duration=5000
)
qtbot.mousePress(track, QtCore.Qt.LeftButton, pos=QtCore.QPoint(300, 300))
animation.valueChanged.connect(on_value_changed)
with qtbot.waitSignal(animation.finished, timeout=10000):
animation.start()
qtbot.mouseRelease(track, QtCore.Qt.LeftButton)
track.location == (end_pos.x(), end_pos.y())
- 使用 pyautogui:
使用此方法无需进行任何更改。
def test_pyautogui(qtbot):
start_pos, end_pos = QtCore.QPoint(300, 300), QtCore.QPoint(400, 300)
track = Tracker()
qtbot.waitUntil(track.isVisible)
def on_value_changed(value):
pyautogui.dragTo(value.x(), value.y(), button="left")
animation = QtCore.QVariantAnimation(
startValue=start_pos, endValue=end_pos, duration=5000
)
pyautogui.moveTo(start_pos.x(), start_pos.y())
pyautogui.mouseDown(button="left")
animation.valueChanged.connect(on_value_changed)
with qtbot.waitSignal(animation.finished, timeout=10000):
animation.start()
track.location == (end_pos.x(), end_pos.y())