pytest-dev / pytest-dev/pytest-qt
BUG: QTest Press/Click not Working
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 455
- Forks
- 72
- Avg merge
- 12h 26m
- Merged PRs (30d)
- 1
Description
Referencing this SO issue, I am experiencing the same problem, even with setMouseTracking enabled (in windows mode, not headless). It appears as if mousePress and mouseClick don't properly release mouse buttons.
MRE
To get hovering to function, I am forced to use mousePress after moves when I shouldn't have to.
def test_menubar_toolbar_hover_triggers_statusbar_messages(app: MainApp, qtbot: QtBot) -> None:
"""Test for correct status bar messages when items are hovered.
For example, when the user clicks 'File' in the menubar and hovers over 'New', the
statusbar message should read 'Create a new project...'. This test currently does not
pass
Args:
app (MainApp): (fixture) Qt main application
qtbot (QtBot): (fixture) Bot that imitates user interaction
"""
window = app.view
menubar = window.menubar
toolbar = window.toolbar
statusbar = window.statusbar
file_menu = window.file_menu
new_action = window.new_action
new_button = toolbar.widgetForAction(new_action)
qtbot.addWidget(menubar)
qtbot.addWidget(file_menu)
qtbot.addWidget(toolbar)
qtbot.addWidget(new_button)
menubar.setMouseTracking(True)
file_menu.setMouseTracking(True)
toolbar.setMouseTracking(True)
new_button.setMouseTracking(True)
file_rect = menubar.actionGeometry(file_menu.menuAction())
new_rect = file_menu.actionGeometry(new_action)
def check_status():
assert statusbar.currentMessage() == 'Create a new project...'
# Assert - Precondition
assert statusbar.currentMessage() == ''
# Act - Menubar
qtbot.wait(10) # In non-headless mode, give time for previous test to finish
qtbot.mouseMove(menubar, file_rect.center())
qtbot.mouseClick(menubar, QtCore.Qt.LeftButton, pos=file_rect.center())
qtbot.mouseMove(file_menu, new_rect.center())
# Assert - Menubar
qtbot.waitUntil(check_status)
# Act - Toolbar
qtbot.wait(10) # In non-headless mode, give time for previous test to finish
qtbot.mouseMove(new_button)
# Assert - Toolbar
qtbot.waitUntil(check_status)
Solution
pyqtgraph has implemented a solution that works: write custom mouse movement methods instead of wrapping QTest:
# Alternative: replace qt_api with qtpy
# from qtpy import QtCore, QtGui, QtTest, QtWidgets
def mousePress(widget, pos, button, modifier=None):
if isinstance(widget, qt_api.QtWidgets.QGraphicsView):
widget = widget.viewport()
if modifier is None:
modifier = qt_api.QtCore.Qt.KeyboardModifier.NoModifier
event = qt_api.QtGui.QMouseEvent(qt_api.QtCore.QEvent.Type.MouseButtonPress, pos, button, qt_api.QtCore.Qt.MouseButton.NoButton, modifier)
qt_api.QtWidgets.QApplication.sendEvent(widget, event)
def mouseRelease(widget, pos, button, modifier=None):
if isinstance(widget, qt_api.QtWidgets.QGraphicsView):
widget = widget.viewport()
if modifier is None:
modifier = qt_api.QtCore.Qt.KeyboardModifier.NoModifier
event = qt_api.QtGui.QMouseEvent(qt_api.QtCore.QEvent.Type.MouseButtonRelease, pos, button, qt_api.QtCore.Qt.MouseButton.NoButton, modifier)
qt_api.QtWidgets.QApplication.sendEvent(widget, event)
def mouseMove(widget, pos, buttons=None, modifier=None):
if isinstance(widget, qt_api.QtWidgets.QGraphicsView):
widget = widget.viewport()
if modifier is None:
modifier = qt_api.QtCore.Qt.KeyboardModifier.NoModifier
if buttons is None:
buttons = qt_api.QtCore.Qt.MouseButton.NoButton
event = qt_api.QtGui.QMouseEvent(qt_api.QtCore.QEvent.Type.MouseMove, pos, qt_api.QtCore.Qt.MouseButton.NoButton, buttons, modifier)
qt_api.QtWidgets.QApplication.sendEvent(widget, event)
def mouseDrag(widget, pos1, pos2, button, modifier=None):
mouseMove(widget, pos1)
mousePress(widget, pos1, button, modifier)
mouseMove(widget, pos2, button, modifier)
mouseRelease(widget, pos2, button, modifier)
def mouseClick(widget, pos, button, modifier=None):
mouseMove(widget, pos)
mousePress(widget, pos, button, modifier)
mouseRelease(widget, pos, button, modifier)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing test_menubar_toolbar_hover_triggers_statusbar_messages with the provided MRE in windows mode, then inspect the existing QTest-backed mouse interaction entry points. Compare their press, release, move, and click behavior with the pyqtgraph ui_testing.py reference. Done means hover status messages work without the extra mousePress workaround and existing interaction tests remain passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- desktop, testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100