Search code examples
pythonqtunit-testingpyqtpyside

How to test PyQt/PySide signals?


I'm trying to test a class that takes "events" from another library and re-dispatches them as Signals/pyqtSignals.

I'm trying to test it by:

  1. Connecting a handler.
  2. Performing some action that should trigger the event (and thus, the Signal/pyqtSignal to be emitted, which should call the handler).
  3. Checking to see if the handler was called.

But the handler never gets called. Or at least it's not getting called by the time I check for it. If I run the lines of the test function one-by-one in a console, the test is successful.

I think the problem is that the Signals aren't getting processed until after the test function completes, but if that's the case, how would I go about testing them?

Here is an example of how I'm trying to test:

from mock import Mock


def test_object():
    obj = MyObject()
    handler = Mock()

    # This connects handler to a Signal/pyqtSignal
    obj.connect('event_type', handler)

    # This should trigger that signal
    obj.do_some_stuff()

    # This fails (call_count is 0)
    assert handler.call_count = 1

    # This will also fail (call_count is 0)
    QtCore.QCoreApplication.instance().processEvents()
    assert handler.call_count = 1

Solution

  • You might need to run a local event loop when waiting for the signals to be dispatched.

    Since you seem to be using pytest (if not, you should consider to!), I'd recommend the pytest-qt plugin. With it, you could write your test like this:

    def test_object(qtbot):
        obj = MyObject()
    
        with qtbot.waitSignal(obj.event_type, raising=True):
            obj.do_some_stuff()