with pycharm i created a small gui with pyqt5 and want to test with pytest and qtbot.
I have a problem to click a menu_entry within the menu and I could need a hint.
I looked at this very helpful post: `pytestqt.mouseMove` to menubar menu widget moves to wrong place in the comments they spoke about the problem to click within in the menubar an entry. (gist.github.com/eyllanesc/ded349044bf43dd79f8c43acb049b263) But the solution code isn't available anymore.
menu
`-> menu_entry1
`-> menu_entry2
Currently the test code looks like this:
def test_menubar_click(app, qtbot) -> None:
app.show()
file_menu = app.ui.menuECIES
menubar = app.ui.menubar
qtbot.add_widget(menubar)
action_rect = menubar.actionGeometry(file_menu.menuAction())
qtbot.wait(1000)
qtbot.mouseMove(menubar, action_rect.center())
qtbot.wait(1000)
qtbot.mouseClick(menubar, QtCore.Qt.LeftButton, pos=action_rect.center())
qtbot.wait(1000)
qtbot.mouseMove(file_menu, action_rect.center())
qtbot.wait(1000)
qtbot.mouseClick(file_menu, QtCore.Qt.LeftButton)
qtbot.wait(1000)
Added Code for minimal, reproducible Example:
main.py
import sys
from qtpy import QtWidgets
from ui.mainwindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setWindowTitle("Test Tool by TTM - v0.1")
self.shortcut_exit = QtWidgets.QShortcut("Alt+Q", self)
self.shortcut_exit.activated.connect(self.close)
self.ui.actionGenerate_new.triggered.connect(self.print_message)
def print_message(self):
print("Menu generate new clicked")
# Hauptprogramm
def main_GUI():
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
return app, window
if __name__ == "__main__":
app, window = main_GUI()
rc = app.exec_()
print("App end is exit code {}".format(rc))
sys.exit(rc)
ui/mainwindow.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui/mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 20))
self.menubar.setObjectName("menubar")
self.menuECIES = QtWidgets.QMenu(self.menubar)
self.menuECIES.setObjectName("menuECIES")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionGenerate_new = QtWidgets.QAction(MainWindow)
self.actionGenerate_new.setObjectName("actionGenerate_new")
self.actionExit = QtWidgets.QAction(MainWindow)
self.actionExit.setObjectName("actionExit")
self.menuECIES.addAction(self.actionGenerate_new)
self.menuECIES.addSeparator()
self.menuECIES.addAction(self.actionExit)
self.menubar.addAction(self.menuECIES.menuAction())
self.retranslateUi(MainWindow)
self.actionExit.triggered.connect(MainWindow.close)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.menuECIES.setTitle(_translate("MainWindow", "ECIE&S"))
self.actionGenerate_new.setText(_translate("MainWindow", "Generate new"))
self.actionExit.setText(_translate("MainWindow", "E&xit!"))
test_main.py
import os
import sys
import pytest
from PyQt5 import QtCore, QtGui, QtTest, QtWidgets
from pytestqt.plugin import QtBot
from main import MainWindow
@pytest.fixture
def app(qtbot):
window = MainWindow()
qtbot.addWidget(window)
return window
def test_menubar_click(app, qtbot) -> None:
# Arrange
app.show()
file_menu = app.ui.menuECIES
menubar = app.ui.menubar
qtbot.add_widget(menubar)
# Act
action_rect = menubar.actionGeometry(file_menu.menuAction())
qtbot.wait(1000)
qtbot.mouseMove(menubar, action_rect.center())
qtbot.wait(1000)
qtbot.mouseClick(menubar, QtCore.Qt.LeftButton, pos=action_rect.center())
qtbot.wait(1000)
qtbot.mouseMove(file_menu, action_rect.center())
qtbot.wait(1000)
TL;DR
PyQt6orPySide6(mouseMoveinPyQt5has a bug)Answer
This is the author of the post and solution to
pytestqt.mouseMoveto menubar menu widget moves to wrong placeI updated the answer because what was originally provided was not fully accurate. Please see the new answer. This should help you.
However, one thing you are missing is that you need to grab the geometry from each submenu item:
This is actually the "menuECIES" button geometry on your menubar, but not any of the submenu items beneath it. You need to get the geometry for
actionGenerate_newandactionExit.and then click those.
Your test function would look like this:
You're not asserting anything though, so the test will pass without doing anything.