如何使用QTest模拟触发PySide2菜单栏Tool下的Save保存功能
问题描述
我正尝试使用QTest模拟保存功能(菜单栏Tool分类下的Save选项),但暂时没有找到可行的实现思路,相关代码如下:
主程序代码
#!/usr/bin/python from PySide2.QtCore import Qt, QEvent from PySide2.QtWidgets import QApplication from PySide2.QtGui import (QTextCharFormat, QIcon, QKeySequence, QBrush, QColor, QTextDocument, QFont, QTextCursor, QTextBlockFormat, QFontDatabase) from PySide2.QtWidgets import (QPlainTextEdit, QSizePolicy, QApplication, QLabel, QGridLayout, QMessageBox, QToolBar, QTextEdit, QCheckBox, QAction, QTableWidget, QTableWidgetItem, QHeaderView, QMenu, QWidget) from PySide2.QtCore import Qt, QSize, QRegExp, QFile, QTextStream, QRect from PySide2.QtWidgets import (QMainWindow, QVBoxLayout, QPlainTextEdit, QGridLayout, QGroupBox, QListWidget, QHBoxLayout, QLabel, QLineEdit, QMenuBar, QPushButton, QMessageBox, QDialog, QTextEdit, QVBoxLayout, QWidget, QFormLayout, QCheckBox, QDialogButtonBox, QTableWidget, QTableWidgetItem, QHeaderView) import sys class Window(QMainWindow): def __init__(self, app): super().__init__() def create_widget(self): self.create_menu() self.plain_textedit = QPlainTextEdit() self.plain_textedit.setMouseTracking(True) self.plain_textedit.viewport().installEventFilter(self) main_layout = QVBoxLayout() main_layout.addWidget(self.toolbar) main_layout.addWidget(self.plain_textedit) self.window = QWidget() self.window.setLayout(main_layout) self.setCentralWidget(self.window) def create_menu(self): """ create menu bar into window """ self.toolbar = QToolBar() self.toolbar.setStyleSheet("QToolBar {background: #ff8000}") self.addToolBar(Qt.TopToolBarArea, self.toolbar) menu = QMenu("&Tool", self) self.menuBar().addMenu(menu) self.actionSave = QAction(QIcon.fromTheme('document-save'), "&Save", self, shortcut=QKeySequence(Qt.CTRL+Qt.Key_W), triggered=self.save_data, enabled=True) self.toolbar.addAction(self.actionSave) menu.addAction(self.actionSave) menu.addSeparator() def save_data(self): pass def eventFilter(self, obj, event): if obj is self.plain_textedit.viewport(): print ("plain_1") return super().eventFilter(obj, event) def main(): app = QApplication([]) window = Window(app) window.create_widget() window.show() app.exec_() if __name__ == "__main__": sys.exit(main())
界面示意图

测试代码
#!/usr/bin/python import os env = os.environ import unittest import logging from PySide2.QtWidgets import QApplication from PySide2.QtTest import QTest from PySide2.QtCore import Qt, QEvent from debug2 import Window class test(unittest.TestCase): def setUp(self): self.app = QApplication.instance() if self.app is None: self.app = QApplication([]) self.window = Window(self.app) self.window.create_widget() self.window.show() #to open gui and helpful for debug #self.app.exec_() def tearDown(self): self.app.deleteLater() def test_save_data(self): actions = self.window.menuBar().actions() for action in actions: sub_commands = action.menu().actions() for sub_command in sub_commands: if sub_command.text() == "&Save": print (dir(QTest)) QTest.mouseClick(self.window.window, Qt.LeftButton) #print (sub_command, sub_command.objectName(), sub_command.text()) if __name__ == '__main__': unittest.main()
解决方案
共有三种常用实现方案,可根据测试需求选择:
方案1:直接触发Save动作信号(最简洁)
菜单、工具栏、快捷键触发保存最终都会调用QAction的trigger()信号,直接调用该方法即可触发save_data,不需要模拟UI点击,测试逻辑稳定不易受界面布局影响。
修改后的test_save_data代码:
def test_save_data(self): save_action = None # 查找Save对应的QAction for action in self.window.menuBar().actions(): if action.text() == "&Tool": for sub_action in action.menu().actions(): if sub_action.text() == "&Save": save_action = sub_action break break # 校验是否找到目标动作 self.assertIsNotNone(save_action, "未找到Tool菜单下的Save选项") # 触发保存动作 save_action.trigger() # 此处可添加自定义断言,校验save_data执行后的逻辑是否符合预期
方案2:模拟快捷键触发
代码中已经给Save选项绑定了Ctrl+W快捷键,直接模拟用户按键即可触发,更贴近真实操作场景:
def test_save_data(self): # 模拟按下Ctrl+W快捷键 QTest.keyClick(self.window, Qt.Key_W, Qt.ControlModifier) # 后续断言逻辑
方案3:模拟用户点击菜单流程
如果需要完全复现用户点击菜单栏→点击Tool→点击Save的完整操作,可使用该方案:
def test_save_data(self): # 查找Tool菜单动作 tool_action = None for action in self.window.menuBar().actions(): if action.text() == "&Tool": tool_action = action break self.assertIsNotNone(tool_action, "未找到Tool菜单") # 点击菜单栏上的Tool选项展开菜单 tool_rect = self.window.menuBar().actionGeometry(tool_action) QTest.mouseClick(self.window.menuBar(), Qt.LeftButton, Qt.NoModifier, tool_rect.center()) # 查找Save选项 save_action = None for sub_action in tool_action.menu().actions(): if sub_action.text() == "&Save": save_action = sub_action break self.assertIsNotNone(save_action, "未找到Save选项") # 点击展开菜单里的Save选项 save_rect = tool_action.menu().actionGeometry(save_action) QTest.mouseClick(tool_action.menu(), Qt.LeftButton, Qt.NoModifier, save_rect.center()) # 后续断言逻辑
内容的提问来源于stack exchange,提问作者user765443
相关产品推荐
相关产品推荐

