PyQt & unittest - 测试信号和槽

4

我正在为一个PyQt应用编写单元测试,它严重依赖信号和槽。为了正确地进行测试,我必须检查是否发送了正确的信号。

最佳方法是什么?我看到Qt库有一个QSignalSpy,但我在PyQt中找不到任何参考。我唯一能想到的选择是模拟发射,例如:

import testedmodule

def myemit(signal):
    ....

testedmodule.QObject.emit = myemit

但我希望有更好的方法。

编辑:
我的模块作为线程运行,在这种情况下,覆盖实例的发射不再起作用,因此我更新了上面的代码以反映这一点。


让 PyQt 的作者 Phil 知道这是需要的。他会添加它或建议解决方法。 - Kaleb Pederson
3个回答

1

这是我自己提出的更详细版本,不一定是单元测试的最佳解决方案,但我认为对于其他遇到此问题的人来说会很有帮助:

Carlos Scheidegger 在 pyqt 邮件列表上发布了此内容(http://thread.gmane.org/gmane.comp.python.pyqt-pykde/9242/focus=9245)。

_oldConnect = QtCore.QObject.connect
_oldDisconnect = QtCore.QObject.disconnect
_oldEmit = QtCore.QObject.emit

def _wrapConnect(callableObject):
    """Returns a wrapped call to the old version of QtCore.QObject.connect"""
    @staticmethod
    def call(*args):
        callableObject(*args)
        _oldConnect(*args)
    return call

def _wrapDisconnect(callableObject):
    """Returns a wrapped call to the old version of QtCore.QObject.disconnect"""
    @staticmethod
    def call(*args):
        callableObject(*args)
        _oldDisconnect(*args)
    return call

def enableSignalDebugging(**kwargs):
    """Call this to enable Qt Signal debugging. This will trap all
    connect, and disconnect calls."""

    f = lambda *args: None
    connectCall = kwargs.get('connectCall', f)
    disconnectCall = kwargs.get('disconnectCall', f)
    emitCall = kwargs.get('emitCall', f)

    def printIt(msg):
        def call(*args):
            print msg, args
        return call
    QtCore.QObject.connect = _wrapConnect(connectCall)
    QtCore.QObject.disconnect = _wrapDisconnect(disconnectCall)

    def new_emit(self, *args):
        emitCall(self, *args)
        _oldEmit(self, *args)

    QtCore.QObject.emit = new_emit

只需调用enableSignalDebugging(emitCall = foo),并窥探您的信号,直到您感到恶心为止 :)

1
注意,QSignalSpy在PyQt5中作为QtTest.QSignalSpy可用

1

您可以尝试将槽连接到信号,准备好测试,然后调用qApp.processEvents()来让信号传播。但我认为这并不是100%可靠的。

遗憾的是,QSignalSpy确实不是PyQt的一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接