python - 如何使用 pytest-qt 点击 QMessageBox?
问题描述
我正在为PyQt
具有pytest-qt
. 我想创建打开图形窗口,做一些测试然后关闭窗口,而不是为每个测试打开一个新窗口,即。对窗口本身使用模块夹具。我通过调用本地函数 aQtBot
而不是使用默认夹具,并删除了嘲笑者,成功地完成了这部分工作。所以我非常接近我的目标。
但是,但我无法关闭窗口(并测试QMessageBox
关闭事件)。
我举了一些例子,比如
如何处理模态对话框及其git讨论,或者qmessage问题;这似乎接近我的问题。建议使用计时器等待QMessageBox
出现然后单击按钮选项,但显然我无法正确应用它们。在我的尝试中,pytest
获得关闭需求,而不是点击dialog
框。所以,我必须点击自己才能完成测试。
这是一个小例子,带有文件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)
和pytest
名为的文件test_GUI.py
:
#!/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")
知道我缺少什么吗?任何其他想法或建议也将不胜感激。
解决方案
在您的尝试中,您正在创建一个QMessageBox
与使用静态方法创建的不同的新方法QMessageBox::question()
,因此即使您单击它也不起作用。
这个想法是获得QMessageBox
显示的,在这种情况下,我们将利用它,因为它是活动窗口,所以我们可以使用QApplication::activeWindow()
. 获取 QMessageBox 的另一种方法是通过以下方式使用 imageViewer 和 QMessageBox 之间的关系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()
推荐阅读
- python - 无法弄清楚为什么我在尝试获取 CSV 行数时不断收到 KeyError
- sql - 需要将其转换为 MongoDB 形式
- javascript - 将复杂的对象数组操作为具有键值数组的对象
- python - AttributeError:找不到 PyAudio;检查安装(语音识别)
- python - 我使用 Paramiko 的 Python 脚本在 IDE (PyCharm) 和命令行中完美运行,但不能在 AWS Lambda 上运行
- node.js - 如何获取通过请求连接的用户的本地IP地址 - Nodejs
- android - 共享元素过渡:过渡闪烁,因为目标片段具有嵌套的滚动视图
- javascript - 根据 Parent 节点 id 或 Umbraco 中页面的当前 id 搜索内容
- selenium-webdriver - 自动打开太多 Edge 实例,并显示“错误:file_io_win.cc(180)] CreateFile settings.dat:访问被拒绝。(0x5)”
- loops - 循环遍历未知属性的 Grails 对象的所有字段