Tcl/Tk - automating GUI testing
I want to automate the testing of my GUI. I went through the followi开发者_StackOverflow社区ng post but if someone can post a sample test code for the following example it would be much easier for me to understand.
The following is my simple Hello World code.
namespace eval Gui {
}
proc Gui::hello {} {
toplevel .hello
wm title .hello "Hello"
wm resizable .hello 0 0 ;# not resizable
# create a frame to hold the check widgets
set f [frame .hello.boolean -borderwidth 10]
pack $f -side top
# OK and Cancel buttons
button .hello.ok -text "OK" -command [list Gui::Ok .hello ]
button .hello.cancel -text "Cancel" -command [list Gui::cancel .hello ]
pack .hello.cancel .hello.ok -side right
bind .hello <Return> {Gui::Ok .hello ; break}
bind .hello <Escape> {Gui::cancel .hello ; break}
}
proc Gui::Ok { arg } {
set x [list puts "Hello world!"]
eval $x
destroy $arg
}
proc Gui::cancel { arg } {
destroy $arg
}
#-------------------------------------------------------------------
# Gui main window
#-------------------------------------------------------------------
proc Gui::initialize { } {
# build the frame which contains menu options
frame .mbar -relief raised -bd 2
frame .mdummy -width 200 -height 240
pack .mbar .mdummy -side top -fill x
# menu options
menubutton .mbar.command -text Command -underline 0 -menu .mbar.command.menu
pack .mbar.command -side left
# menu under command options
menu .mbar.command.menu -tearoff 0
.mbar.command.menu add command -label "Hello..." -command [list Gui::hello]
}
#-------------------------------------------------------------------
# main code
#-------------------------------------------------------------------
Gui::initialize
I want to test Command -> Hello ... -> OK
and see if it outputs Hello world!
. It would be great if someone can post a sample code which simulates these clicks and tests it automatically.
The simplest way to make a button behave like it's been clicked is to use its invoke
method:
.hello.ok invoke
Of course, then you've also got to capture the result of that invocation; writing to stdout not being the most useful thing in the world when it comes to testing (unless you wrap a test harness in another process and … well, let's just leave it as being much more work). Restructuring your code so that you can use a different back-end when testing the GUI part of it will help you a lot here.
It's also possible to go below the level of method invocations to the point where you start faking events with event generate
. That's a lot more work because you can't just generate mouse clicks and key presses; you also have to synthesize <Enter>
and <FocusIn>
events so that Tk's widgets arm themselves properly. Here's an example (-when tail
puts the event on the end of the event queue):
event generate .hello.ok <Enter> -when tail
event generate .hello.ok <ButtonPress-1> -when tail
event generate .hello.ok <ButtonRelease-1> -when tail
You can even go to the point of generating events positioned relative to the toplevel or the whole root window (though Tk will only deliver them internally; it doesn't send events to other apps as that would be rather rude) but I advise leaving positions out if you don't need them as they make your code very fragile to (usually unimportant) things like detailed font changes.
Good luck with testing your GUI. It's difficult to do well. Making your code so that the GUI is decoupled from the back end by passing in the scripts to configure as arguments where appropriate (pretty trivial to do in Tcl, and equivalent to things like “mocking” done in other languages) will help a lot by stopping you having to test everything at once. That will help keep you sane.
精彩评论