如何使用pytest-qt单击QMessageBox? [英] How to click on QMessageBox with pytest-qt?

查看:209
本文介绍了如何使用pytest-qt单击QMessageBox?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用pytest-qtPyQt应用程序创建一些单元测试. 我想创建一个打开的图形窗口,先做一些测试然后关闭窗口,而不是为每个测试都打开一个新窗口.对窗口本身使用模块夹具. 我成功地完成了这一部分,方法是在本地函数中调用QtBot而不是使用默认的固定装置,并删除了模拟装置.所以我很接近我的目标.

I am creating some unit tests for a PyQt application with pytest-qt. And I would like to create open the graphical window, do some tests then close the window, rather than open a new window for every test, ie. use a module fixture for the window itself. I succeeded to do this part, by calling in a local function a QtBot rather than using the default fixture, and removing the mocker ones. So I am pretty close to my objective.

但是,但是我无法关闭窗口(并测试QMessageBox的关闭事件).

However, but I am not able to close the window (and test the QMessageBox for closing event).

我喜欢红色的例子 如何处理模式对话框及其 git 讨论,或

I red examples like how to handle modal dialog and its git discussion, or the qmessage question; which seem to be close to my question. It is suggested to use a timer to wait for the QMessageBox to appear then click on a button choice, but visibly I am not able to apply them correctly. In my attempt, pytest get the closing demand, but not the click on the dialog box. So, I have to click myself to finish the test.

这是一个小示例,文件为GUI.py:

Here is a small example, with file GUI.py:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys

from PyQt5 import QtGui, QtCore, QtWidgets

from PyQt5.QtWidgets import *
from PyQt5.QtCore import QCoreApplication, Qt, QObject
from PyQt5.QtGui import QIcon


class Example(QMainWindow):
    def __init__(self, parent = None):
        super().__init__()
        self.initUI(self)

    def initUI(self, MainWindow):
        # centralwidget
        MainWindow.resize(346, 193)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        # The Action to quit
        self.toolb_action_Exit = QAction(QIcon('exit.png'), 'Exit', self)
        self.toolb_action_Exit.setShortcut('Ctrl+Q')
        self.toolb_action_Exit.triggered.connect(self.close)

        # The Button
        self.btn_prt = QtWidgets.QPushButton(self.centralwidget)
        self.btn_prt.setGeometry(QtCore.QRect(120, 20, 89, 25))
        self.btn_prt.clicked.connect(lambda: self.doPrint() )
        self.btn_quit = QtWidgets.QPushButton(self.centralwidget)
        self.btn_quit.setGeometry(QtCore.QRect(220, 20, 89, 25))
        self.btn_quit.clicked.connect(lambda: self.close() )

        # The textEdit
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit.setGeometry(QtCore.QRect(10, 60, 321, 81))

        # Show the frame
        MainWindow.setCentralWidget(self.centralwidget)
        self.show()

    def doPrint(self):
        print('TEST doPrint')

    def closeEvent(self, event):
        # Ask a question before to quit.
        self.replyClosing = QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QMessageBox.Yes |
            QMessageBox.No, QMessageBox.No)

        if self.replyClosing == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()


def main_GUI():
    app = QApplication(sys.argv)
    imageViewer = Example()
    return app, imageViewer


if __name__ == '__main__':
    app, imageViewer =main_GUI()
    rc= app.exec_()
    print('App end is exit code {}'.format(rc))
    sys.exit(rc)

和名为test_GUI.pypytest文件:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os, sys
import pytest

from PyQt5 import QtGui, QtCore, QtWidgets, QtTest
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QCoreApplication, Qt, QObject

from pytestqt.plugin import QtBot

GUI = __import__('GUI')


@pytest.yield_fixture(scope="module")
def qtbot_session(qapp, request):
    print("  SETUP qtbot")
    result = QtBot(qapp)
    with capture_exceptions() as exceptions:
        yield result
    print("  TEARDOWN qtbot")


@pytest.fixture(scope="module")
def Viewer(request):
    print("  SETUP GUI")
    app, imageViewer = GUI.main_GUI()
    qtbotbis = QtBot(app)
    # qtbotbis.addWidget(imageViewer)
    # qtbotbis.wait_for_window_shown(imageViewer)
    QtTest.QTest.qWait(0.5 *1000)
    yield app, imageViewer, qtbotbis

    # EXIT
    # mocker.patch.object(QMessageBox, 'question', return_value=QMessageBox.Yes)
    # imageViewer.toolb_action_Exit.trigger()
    def handle_dialog():
        # while not imageViewer.replyClosing.isVisible():
        #   app.processEvents()
        box = QMessageBox()
        box.setStandardButtons(QMessageBox.Yes)
        button = box.button(QMessageBox.Yes)
        qtbotbis.mouseClick(button, QtCore.Qt.LeftButton)
    QtCore.QTimer.singleShot(100, handle_dialog)
    qtbotbis.mouseClick(imageViewer.btn_quit, QtCore.Qt.LeftButton, delay=1)
    assert imageViewer.close()
    print("  TEARDOWN GUI")


class Test_GUI() :
    def test_interface(self, Viewer):
        print("  beginning ")
        app, imageViewer, qtbot = Viewer
        qtbot.mouseClick( imageViewer.btn_prt, QtCore.Qt.LeftButton )
        QtTest.QTest.qWait(0.5 *1000)
        assert True
        print(" Test passed")

对我想念的东西有什么想法吗?任何其他想法或建议也将不胜感激.

Any idea of what I am missing ? Any other idea or suggestion would also be appreciate.

推荐答案

尝试创建的新QMessageBox与使用静态方法QMessageBox::question()创建的新QMessageBox不同,因此即使单击它也不会工作.

In your attempt you are creating a new QMessageBox that is different from the one created with the static method QMessageBox::question() so even if you click it will not work.

想法是获取所示的QMessageBox,在这种情况下,我们将利用它的优势,因为它是活动窗口,因此我们可以使用QApplication::activeWindow()来获取它.获取QMessageBox的另一种方法是通过findChild()使用图像查看器与QMessageBox之间的关系:

The idea is to obtain the QMessageBox shown, and in this case we will take advantage of that since it is the active window so we can obtain it using QApplication::activeWindow(). Another way to get the QMessageBox is to use the relationship between imageViewer and the QMessageBox through findChild():

@pytest.fixture(scope="module")
def Viewer(request):
    print("  SETUP GUI")

    app, imageViewer = GUI.main_GUI()
    qtbotbis = QtBot(app)
    QtTest.QTest.qWait(0.5 * 1000)

    yield app, imageViewer, qtbotbis

    def handle_dialog():
        messagebox = QtWidgets.QApplication.activeWindow()
        # or
        # messagebox = imageViewer.findChild(QtWidgets.QMessageBox)
        yes_button = messagebox.button(QtWidgets.QMessageBox.Yes)
        qtbotbis.mouseClick(yes_button, QtCore.Qt.LeftButton, delay=1)

    QtCore.QTimer.singleShot(100, handle_dialog)
    qtbotbis.mouseClick(imageViewer.btn_quit, QtCore.Qt.LeftButton, delay=1)
    assert imageViewer.isHidden()

这篇关于如何使用pytest-qt单击QMessageBox?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆