Reputation: 113
I have a pyqt application that I'm writing unit tests for, and it relies heavily on signals and slots. To properly test it, I have to check that the correct signals are sent.
What is the best way to do this? I see that the Qt library has a QSignalSpy, but I can't find any reference to this in PyQt. The only option I can think of is to mock emit, e.g.
import testedmodule
def myemit(signal):
....
testedmodule.QObject.emit = myemit
but I'm hoping there is a better way.
Edit:
My module is run as a thread, in that case overriding emit of an instance no longer worked after starting the thread so I updated the code above to reflect this.
Upvotes: 4
Views: 3695
Reputation: 113
This is a more elaborate version of what I suggested myself, not necessarily the best solution for unittest, but I think it will be of interest to others that come across this:
Posted by Carlos Scheidegger on the pyqt mailing list (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
just call enableSignalDebugging(emitCall=foo) and spy your signals until you're sick to your stomach :)
Upvotes: 1
Reputation: 12175
You can try connecting a slot to your signal, prepare your test, then call qApp.processEvents() to let the signal propagate. But I don't think it's 100% reliable.
It's a pity that QSignalSpy is not part of PyQt indeed.
Upvotes: 1