Are you sure you want to unit test the GUI? Your example of complexity involves more than 1 unit and is therefore an integration test.
If you really want to unit test, you should be able to instantiate a single class providing mocks or stubs for its dependencies, then call methods on it like the GUI framework would for e.g. a user click. This can be tedious and you have to know exactly how the GUI framework dispatches user input to your classes.
My advice is to put even more stuff in models. For your given example you could create a FilterManager which abstracts all the filter/select/display stuff behind a single method. Then unit test it.
There is a great way to test PyGTK functions and widgets directly, without going through acceptance/functional/integration testing frameworks that clikety their way into oblivion. I learned about this in this post which is fairly self explanatory. But the basic idea is that you treat your widgets as functions/classes, and you can test them directly. If you need to process callbacks and so on, there's a neat trick that I will reproduce here:
import time
import gtk
# Stolen from Kiwi
def refresh_gui(delay=0):
while gtk.events_pending():
gtk.main_iteration_do(block=False)
time.sleep(delay)
As mentionned in the blog post, this code is LGPL. Otherwise, when you think about it, as long as you don't show()
windows or widgets, you can test them all you want and they should behave as if they were real because, in a way, they are. They are just not displayed.
Of course, you need to simulate interaction on buttons and interactive widgets yourself by calling clicked()
on a button for example. See again Ali Afshar's excellent post about unit testing in PyGTK.
In sticking with the theme that Jürgen was correct in that I'm not interested in unit testing, but actually interested in integration testing, I also found this framework from freedesktop.org: http://ldtp.freedesktop.org/wiki/
It allows automating a variety of tests for Accessibility-enabled GUI applications (including GTK, Qt, Swing, etc).
You can use a X11 framebuffer:
Xvfb :119 -screen 0 1024x768x16 &
export DISPLAY=:119
... run your tests
Be sure, to not enter gtk.main()
, since this would wait for mouse or keyboard input. You can use this pattern to let gtk handle all events:
def refresh_gui():
while gtk.events_pending():
gtk.main_iteration_do(block=False)
AFAIK you can't see your application, but you can test your callbacks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With