Alex Tereshenkov
Alex Tereshenkov

Reputation: 3620

How to use QTest to send a Ctrl-key combination in PyQt5?

I use PyQt5.6, Python 3.5 and Windows for a hobby project where I have an app with some actions (QAction) that have shortcuts set (for key combinations Ctrl-N and Ctrl-B, for example). I have written unit tests to verify that those actions can be triggered and they do what they should.

However, I am not able to find any working example of how to trigger an action using a shortcut that has been set when writing a unit test with QTest.

To support the question, this is the minimal application code:

import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, QLabel


########################################################################
class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.setGeometry(50, 50, 500, 300)

        action1 = QAction("&Action1", self)
        action1.setShortcut("Ctrl+U")
        action1.triggered.connect(self.update_label)

        self.label = QLabel('Empty', self)
        self.setCentralWidget(self.label)

        main_menu = self.menuBar()
        file_menu = main_menu.addMenu("&File")
        file_menu.addAction(action1)

        self.show()

    def update_label(self):
        print("updating label")
        self.label.setText('Updated label')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    GUI = Window()
    sys.exit(app.exec_())

The app has one action which can be triggered by Ctrl-U. The app works as expected. Now I have written a unit test suite:

import unittest
from PyQt5.QtWidgets import QApplication
from PyQt5.Qt import QKeySequence
from PyQt5.Qt import Qt
from myapp import Window
from PyQt5.QtTest import QTest


########################################################################
class Test(unittest.TestCase):

    #----------------------------------------------------------------------
    def setUp(self):
        self.app = QApplication([])
        self.ui = Window()
        self.menu = self.ui.menuBar()

    #----------------------------------------------------------------------
    def test_update_label_from_menu(self):
        self.assertEqual(self.ui.label.text(), 'Empty')
        self.menu.actions()[0].menu().actions()[0].trigger()
        self.assertEqual(self.ui.label.text(), 'Updated label')

    #----------------------------------------------------------------------
    def test_update_label_from_shortcut(self):
        self.assertEqual(self.ui.label.text(), 'Empty')
        QTest.keyClicks(self.ui, 'U', Qt.ControlModifier)
        print(self.ui.label.text())

        QTest.keyPress(self.ui, 'U', Qt.ControlModifier)
        print(self.ui.label.text())

        QTest.keyPress(self.ui, Qt.Key_U, Qt.ControlModifier)
        print(self.ui.label.text())

        self.assertEqual(self.ui.label.text(), 'Updated label')
        return

    #----------------------------------------------------------------------
    def tearDown(self):
        pass

When the test test_update_label_from_menu is executed, the action is being triggered and I can see that the label text has been updated and the test passes. However, I am not able to send the shortcut properly using QTest in the test_update_label_from_shortcut test (I am trying various combinations). The test fails.

How do I do send the event such as pressing Ctrl-N using QTest?

UPDATE: It looks like I am already using the suggested way in this answer (which is calling QTest.keyClicks(self.window, 'n', Qt.ControlModifier)) and it does not work for me. Not sure if this matters that much, but the answer refers to PySide, yet I am on PyQt.

UPDATE 2: In order to be able to make the test pass, I had to add QTest.qWaitForWindowExposed(self.ui) line in the setUp. Then the key presses can be sent using shortcuts.

Upvotes: 2

Views: 859

Answers (0)

Related Questions