I have been unit-testing GUIs for a while, and was surprised to learn that others had overlooked my most basic technique. For some UI libraries, you must display the window before you simulate clicks on it. This makes running SuperTest
a pain. Either windows block until you close them, or your program closes them automatically, so they flash on the screen and slow the run down.
The technique I use is based on how the "toolkit" class of GUIs (Tk, GTK, etc.) work. You create windows with controls on them, then call "mainloop" to receive user events and dispatch the controls' calls-back.
My technique creates the windows, puts data in them, reads it out, and then does not call mainloop. Hence its name.
Following is a sample of this technique in freshly hatched RubyLanguage
. Play with $visible to either see & interact with the window, or leave it hidden in batch mode. Comments or additions welcome. -- PhlIp
See also http://www.xp123.com/xplor/xp0001/
for similar article, only about Java. -- mfi
A tuned OneButtonTesting
effort in an MS Windows environment may temporarily call DoEvents
at the end of a test, to visually inspect it.
A complete UI mini-framework developed using this technique (and ScalableVectorGraphics
) appears here: http://wiki.rubygarden.org/Ruby/page/show/SvgCanvas
$visible = false
def assert bool
throw "get a clue" if not bool
def testedFunction win
cbitems = [ "item0", "item1 item1" ]
box1 = Gtk::VBox::new(false, 0)
box2 = Gtk::VBox::new(false, 10)
box1.pack_start(box2, true, true, 0)
entry = Gtk::Entry::new()
box2.pack_start(entry, true, true, 0)
cb = Gtk::Combo::new()
box2.pack_start(cb, true, true, 0)
return entry, cb
win = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL)
entry, cb = testedFunction (win)
assert entry.get_text == "hello world"
assert cb.entry.get_text == "hello world"
# click on another cb line
# assert cb.entry.get_text == "item0"
if $visible then
A more complete version of that technique appears here: http://gnomesupport.org/wiki/index.php/TestDrivenDevelopment