Help with automated testing of a QThread that pops a modal dialog
-
Writing some automated tests, and I've got one that's stumping me.
I have a function that can find a specific modal dialog, and it's run via a QTimer: it normally looks like this
QtCore.QTimer.singleShot(90,dialog_watcher.run) self.installer_gui._report_dependency_failure("Unit test","Fake error message") self.assertTrue(dialog_watcher.dialog_found, "Failed to find the expected dialog box")
Works great because
_report_dependency_failure
has a QMessageBox modal that blocks, but the timer continues to work because it's got an event loop.Now I have to test a function that doesn't block: it spins up a QThread and returns, and later (when it completes) it calls the function that opens the modal dialog. So my test needs to block itself until the dialog pops up, gets found, and gets closed. I tried things like:
QtCore.QTimer.singleShot(1000,dialog_watcher.run) self.installer_gui.install() # This does not block while not dialog_watcher.has_run: # has_run gets set at the end of a call to run() QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents,100) print("Finished") # Should happen after one second, right?
That timer runs on the GUI thread (the calling thread), right? What's wrong with my faked event loop there, that the timer doesn't ever seem to fire?
-
Then why not use only mocking and replace the slot so the dialog does not even need to be shown ?
Note that you don't need to switch over your tests. pytest works as well with Python's unittest module.
-
Hi,
What testing framework are you using ?
If not already, you should consider
pytest-qt
. It simplifies writing test of Qt applications.You can then mock the slot called in order to gather information for your test.
-
We use the Python unittest package -- unfortunately I can't migrate away from that (it's a large application, with many existing tests). In this case I don't care about the dialog itself, I have a separate unit test for that. I just need to get it closed.
-
Then why not use only mocking and replace the slot so the dialog does not even need to be shown ?
Note that you don't need to switch over your tests. pytest works as well with Python's unittest module.
-
Then why not use only mocking and replace the slot so the dialog does not even need to be shown ?
Note that you don't need to switch over your tests. pytest works as well with Python's unittest module.
@SGaist said in Help with automated testing of a QThread that pops a modal dialog:
Then why not use only mocking and replace the slot so the dialog does not even need to be shown ?
Hah! Because Iām blind and was looking for the most complicated possible solution? Disconnect the signal. Duh. Thanks for the kick š.
-
I would rather mock the slot than disconnect the signal. By doing so you change the way your application works. The mocking allows you to ensure that the slot still gets called as expected but in a controlled fashion. You can also use that technique for example to simulate when a user would need to input something.