I'm working on a PyQt 4 application for my employer Chess. Of course I'm writing plenty of unit tests for it as well. Those tests have to be cleanly separated from each other, so every test that requires the entire application to be up and running should have its own instance. And this is where it gets tricky, as Qt (and thus PyQt) assumes that there will only be one application, and if that application quits the process quits.
In my unit tests, this is not the case. Every test can potentially start and stop an application, and the test suite will continue running. This caused a segmentation fault (a.k.a. segfault) the second time the QApplication closed.
After a lot of puzzling I found out that QtGui.qApp needs to refer to the running QApplication instance, and be set to
None when the application has been closed. After I implemented this the segfaults went away.
This is my
ApplicationTest mix-in class that I use for controlling my application lifespan. It contains a little trick to stop the application as soon as it has started:
class MyApplicationClass(QtGui.QApplication): started = QtCore.pyqtSignal() def exec_(self): self.started.emit() return QtGui.QApplication.exec_() class _ApplicationTest(object): '''Mix-in class that can start and stop an application.''' APP_CLASS = MyApplicationClass def __init__(self): self.app = None QtGui.qApp = None def create_app(self): '''Creates and returns a new application''' self.app = self.APP_CLASS() QtGui.qApp = self.app return self.app def stop_app(self): '''Stops the application.''' if not self.app: return self.app.started.connect(self.app.quit, type=QtCore.Qt.QueuedConnection) self.app.exec_() QtGui.qApp = None self.app = None