0

I'm trying to make unit tests on classes that involve signals and QTimers. (see the answer to this question for an idealization of one of the classes). I'm having a hard time trying to understand where to put the app.exec_() call without freezing everything and executing the tests with the signals being emitted. Just like in the question I cite, I think the problem here is that I need an event loop but putting in the setUpClass definitely doesn't work. This is the smallest piece of code I made to reproduce my problem, which in reality is with a larger code base.

testSignals.py:

import time
from PySide import QtCore

class TestSignals(QtCore.QObject):

    def __init__(self):
        self.timer = QtCore.QTimer()
        self.myTime = ''
        self.timer.timeout.connect(self.updateTime)
        self.timer.start(100)

    def getTime(self):
        return self.myTime

    def updateTime(self):
        self.myTime = time.strftime('%H:%M:%S')

    def stop(self):
        self.timer.stop()

unitTesting.py:

import unittest
from testSignals import TestSignals 
from PySide import QtGui, QtCore
from testSignals import TestSignals
import sys

class test(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        app = QtGui.QApplication(sys.argv)
        assert id(app) == id(QtGui.qApp) and id(app) == id(QtCore.QCoreApplication.instance())
        cls.test = TestSignals()
        # app.exec_()   # uncommenting this only causes the code to freeze

    def testStarted(self):
        mytime = self.test.getTime()
        self.assertNotEqual(mytime,'','Time is still empty')

if __name__ == '__main__':
    unittest.main()

and the result is a failure of the only test because "mytime" is still empty. Just for clarity, the class does work:

class testConnection():
    def receiveMe(self):
        print(self.test.getTime())
        # print(self.test.getData())

    # signal is emmited when data is changed
    def __init__(self):
        self.test = TestSignals()
        self.test.timer.timeout.connect(self.receiveMe)
        # self.test.start()

app = QtCore.QCoreApplication([])
test = testConnection()
timer = QtCore.QTimer()
timer.singleShot(4000,app.exit)
app.exec_()

produces:

>>>$ python3 testConection.py 
14:50:21
14:50:22
14:50:23
14:50:24
Community
  • 1
  • 1
cauchi
  • 1,463
  • 2
  • 17
  • 45
  • What is the purpose of the timer? Please provide a realistic example and explain what you are really trying to test. – ekhumoro May 19 '15 at 16:42
  • one class is going to read data from a service. That data will be used in a GUI to be plotted or put into tables. The data is to be read every n seconds (n is 1/10, 1/100 or 1/1000). I don't want to check if the data is changed, I want a signal linked to a function to update the change once the data has been read. I can do that, if I get this to work. I would really like to do unit testing on this because the code may grow in the future. – cauchi May 19 '15 at 16:51
  • What I want to test is that the signal is emitted. That seems trivial. But to use signals I need an event loop, which is what I don't know how to implement in the unit test. An example of that would be sufficient. Now that I think about it, I don't even need the timer in the example. I need a signal, a slot, and what I want is to test that. – cauchi May 19 '15 at 20:35
  • You do not need an event-loop for signals in a *single-threaded* app. In that context, they work very much like callbacks (i.e. the connected slots are called synchronously). Have you ever looked at [QTest](http://doc.qt.io/qt-4.8/qtest.html)? There's some example code [here](http://johnnado.com/pyqt-qtest-example/) that you might find useful. – ekhumoro May 19 '15 at 22:04
  • Yes, I had read that, but there are no signals or event loops in that example. I found some examples of testing signals and threads in Qt but in C++ code. The main function of the test is modified, but don't fully understand how to do that in pyside. – cauchi May 20 '15 at 08:38
  • What *specific* problem are you trying to solve regarding testing signals? Without some clear, realistic example code, there is not much more that can be said on this topic. – ekhumoro May 20 '15 at 16:19
  • what about the code I wrote in the question? that is as specific as you can get. Is clear and realistic. If I cannot do a unit test on such a small piece of code I cannot do it on a bigger one. – cauchi May 21 '15 at 12:35
  • The first thing I asked was: what is the purpose of the timer? In a later comment you said: "I don't even need the timer". If you get rid of the timer, you don't need an event-loop to test signals. That is why the current example is unclear. – ekhumoro May 21 '15 at 14:45

0 Answers0