You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用pytest-qt测试QFileDialog的directoryEntered信号触发槽函数

问题分析
  • 时序逻辑错误:waitSignal 必须在信号触发前启动监听,你之前的写法要么先发射信号再调用waitSignal,信号已经触发完了才开始监听自然捕获不到;要么先调用waitSignal,阻塞到超时才会执行后面的信号发射逻辑,自然也捕获不到。
  • Mock生命周期错误:你把信号触发逻辑放在with mock.patch块内部,但槽函数是Qt事件循环异步执行的,等事件循环处理信号调用槽函数的时候,with块已经退出,mock 已经被还原为原生方法,当然统计不到调用次数。
  • 冗余操作:既然你已经确认connect绑定正常,直接emit信号测试逻辑即可,不需要额外找原生按钮点击,增加不必要的复杂度。
正确测试代码
import pathlib
from unittest import mock
from PyQt5 import QtWidgets, QtCore
# 这里替换为你自己的SaveProjectDialog导入路径
from save_project_dialog_class import SaveProjectDialog

def test_directoryEntered_triggers_on_dir_entered(qtbot, tmpdir):
    project = mock.Mock()
    project.main_window = QtWidgets.QWidget()
    project.home_dir_path = pathlib.Path(str(tmpdir))
    fd = SaveProjectDialog(project)
    
    # mock 作用域覆盖整个信号处理周期
    with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
        # waitSignal 作为上下文管理器,进入即开始监听信号,块内执行触发信号的逻辑
        with qtbot.waitSignal(fd.directoryEntered, timeout=1000):
            fd.directoryEntered.emit('dummy')
        # 退出waitSignal块时信号已处理完成,mock仍在生效期,可正常断言
        mock_entered.assert_called_once_with('dummy')
原理解释

qtbot.waitSignal作为上下文管理器使用时,进入代码块就会启动对目标信号的监听,代码块内执行触发信号的逻辑,整个块会阻塞直到收到目标信号或者超时,退出块时事件循环已经处理完该信号关联的所有槽函数调用。再配合外层的mock作用域覆盖整个处理周期,就能正确统计槽函数的调用情况。

内容的提问来源于stack exchange,提问作者mike rodent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 12:06:03