Then Dont Call Main Loop

last modified: July 6, 2006

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 and RubyLanguage and RubyTk) appears here: http://wiki.rubygarden.org/Ruby/page/show/SvgCanvas


require 'gtk'

$visible = false

def assert bool
throw "get a clue" if not bool
end

def testedFunction win
   cbitems = [ "item0", "item1 item1" ]
   win.border_width(0)

   box1 = Gtk::VBox::new(false, 0)
   win.add(box1)
   box1.show

   box2 = Gtk::VBox::new(false, 10)
   box2.border_width(10)
   box1.pack_start(box2, true, true, 0)
   box2.show

   entry = Gtk::Entry::new()
   entry.set_text("hello world")
   entry.select_region(0, 5)
   box2.pack_start(entry, true, true, 0)
   entry.show

   cb = Gtk::Combo::new()
   cb.set_popdown_strings(cbitems)
   cb.entry.set_text("hello world")
   box2.pack_start(cb, true, true, 0)
   cb.show
   return entry, cb
end

def test_entryThing
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
 win.show
  Gtk.main
 else
 win.destroy
end
end

test_entryThing

A more complete version of that technique appears here: http://gnomesupport.org/wiki/index.php/TestDrivenDevelopment


See GuiTesting, GuiUnitTesting, GuiTestingPatterns, TestFirstUserInterfaces


Loading...