Re: how do you test GUI functionality?
From: John Seal (johnseal_at_indy.net)
Date: 11/05/03
- Previous message: Aaron Montgomery: "latex \write18 and pipes"
- In reply to: Bryan Oakley: "how do you test GUI functionality?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Wed, 05 Nov 2003 01:28:20 GMT
In article <2VTpb.1572$z04.432@newssvr22.news.prodigy.com>,
Bryan Oakley <bryan@bitmover.com> wrote:
> For those of you who write applications with Tk, how do you
> test the functionality of your applications?
I wrote a small test harness called Classic Automated Regression Test
(CART; Classic is the name of the application). It uses comm to work
the app by remote control without permanently injecting any debug code.
It is implemented as a package, and exports procedures for grabbing
resources from a hardware pool, pushing buttons (any kind, even menu
commands), entering values, providing simulated inputs, extracting state
data, and testing results.
Individual tests are Tcl scripts which primarily call our exported
domain-specific cart:: procedures, but they can use the full power of
Tcl. The test harness takes care of teeing all stdout into serialized
log files, with timestamps on each line. Tests can be grouped together
into larger test suites. The exported functions of cart:: do a fairly
good job of insulating the test developer from needing intimate
knowledge of the app's internal structure, but I'm afraid that testing
certain values requires at least a knowledge of the variable names.
This is for an interrupt-driven realtime control application with an
*extremely* complex GUI, with a server that talks to the equipment via
GPIB and dozens of clients distributed over many remote hosts. Total
code on the order of 5000 SLOC.
So far I've only used it "officially" for unit testing. Some people are
impressed, but it's not clear if I'll be allowed to develop a full
regression test suite, as I hope.
I have one script which tests handing off control from one GUI to
another; it's fascinating to watch two GUIs open on the screen,
reposition themselves to be side-by-side, buttons magically pushing on
one GUI to setup the scenario, then handing off to the other GUI. A log
window keeps a running commentary on what's happening, and if the states
of the GUIs match at the end, a PASS message is generated. Afterwards,
the same info is there in the log file, with timestamps. Sweet!
For an example, here is the source for the button-pushing procedure:
# Returns a script to push a specified button in a GUI.
# The buttonName is the text of the button as it appears in the GUI.
# This procedure DOES NOT push the button; that doesn't happen until
# you send the resulting script to the GUI for evaluation.
proc cart::push {buttonName} {
# This whole thing is the script, all we do is plug in buttonName.
# Note the extensive use of [set] to avoid premature $ substitution.
# The script walks the widget tree by keeping a list of unvisited
# nodes. Each node is removed from the list as it is examined, and
its
# children are added. The first widget whose -text option matches the
# specified buttonName is invoked, and its pathname is returned.
subst -nocommands {
set places {.}
while {[llength [set places]]} {
set place [lindex [set places] 0]
set places [lrange [set places] 1 end]
set places [concat [set places] [winfo children [set place]]]
if {[catch {[set place] cget -text} text]} {continue}
if {![string equal "$buttonName" [set text]]} {continue}
[set place] invoke
return [set place]
}
}
}
And here is a silly pseudocode example of how it might be used:
# Test script for "Doctor" application.
package require cart
namespace import cart::*
set n [need 1 patient]
patient $n [push "Get Sick"]
patient $n [enter temp 101]
patient $n [push "Take Aspirin"]
verify {[patient $n {set temp}] == 98.6} "Aspirin didn't reduce fever!"
pass "Temperature is normal"
Note the use of braces around {set temp}, because we're passing that
literal script to the GUI, rather than a script returned by a call to
[push] or [enter], for example. Note also the implicit FAIL if the
verify condition isn't satisfied.
- Previous message: Aaron Montgomery: "latex \write18 and pipes"
- In reply to: Bryan Oakley: "how do you test GUI functionality?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]