Testing GUIs with TextTest and StoryText
Naturally the first step is to download and install StoryText
To see what StoryText does, try running it with the "videostore.py"
demonstration PyGTK GUI in the "examples" directory in the download.
This ought to work if you've followed the instructions, because StoryText's own GUI uses PyGTK
so you should have installed it! (Note there is now also a Java Swing example
also, Swing users might like to try to use that instead.)
(It might also be an idea to run the example application (here videostore.py) on its own first,
so you can separate what StoryText does from what it does)
You can record a usecase by doing
storytext -r usecase.txt videostore.py
This brings up the Video Store in record mode and StoryText
writes its auto-generated log of what the GUI looks like to the console
as you go along. As a suggestion, add a movie called "Star Wars" like this :
and then exit. This results in StoryText's own dialog coming
up and requesting that you enter "usecase names" for the things
you just did. It gives you the type of the widget, how it identifies it
and a description of the action that was performed on it, and
you can hopefully figure out which row corresponds to which action you did
and name the actions in a suitably high-level language.
The current usecase that will be recorded is previewed in the window at the
bottom as you type to assist you in this process.
Since StoryText 3.10 you will be presented with a choice of properties of the widget
to use for identification, in a drop-down box as shown below. The default will generally
be the most specific option which does not include specifying the widget type. Most of the
time leaving the default in is fine, but sometimes you might want to use a different property
or combination of them for some reason.
Any actions that we don't name will be treated as uninteresting and will
not be recorded. Here is the dialog as it might be filled out just before
you accept it:
Now we are done, and the usecase as shown in the preview window is saved to our "usecase.txt" file.
We can now play it back via:
storytext -p usecase.txt videostore.py
which goes by extremely fast but helpfully describes the GUI changes on the console for us,
somewhat more compactly than when we were recording as it e.g. makes text edits in one go. It
will look something like this:
---------- Window 'The Video Store' ----------
Focus widget is 'Movie Name'
Menu Bar : 'File' (+)
'New Movie Name ' , Text entry , Button 'Add' , Button 'Delete' ,
Button 'Sort' , Button 'Clear'
Showing Notebook with tabs: text info , video view
Viewing page 'video view'
Showing Movie Tree with columns: Movie Name
'Shortcuts:' , Button '_New'
'set movie name to' event created with arguments 'Star Wars'
Edited 'Movie Name' Text entry (set to 'Star Wars')
'add movie' event created with arguments ''
Updated : Movie Tree with columns: Movie Name
-> Star Wars
'close' event created with arguments ''
As you can see, this consists of an initial description of the window appearance
(compare with the screenshot above) and then a series of "event created with arguments"
lines which indicate what StoryText has done, followed by the updates to the UI that resulted.
To see the usecase executing at a more sensible pace so you watch the UI changes, set a delay like this:
storytext -p usecase.txt -d 2 videostore.py
which will wait 2 seconds between each action.
Naturally the information we entered in the dialog has been stored in a file, the "UI map file"
, for us. By default this will have ended up in your home directory under ".storytext/ui_map.conf".
You can control the location of this either by providing its full path via "-m" on the command
line, or by setting the environment variable STORYTEXT_HOME, which points out the directory
where it will be written.
If you open it you should see something like this:
changed = set movie name to
clicked = add movie
[Title=The Video Store]
delete-event = close
The basic idea is that GUI changes will cause changes in this file but not in the "usecases" themselves. StoryText identifies widgets by name, title, label and type, in that order (tooltips and View IDs are also used in Eclipse RCP). Obviously here we are identfiying the "Add" button by its Label, which will break down if the UI contains anything else labelled "Add". Likewise, the title of our window might vary from run to run. For robustness it's therefore sometimes necessary to assign widget names in your code, at which point this file should be updated with "Name=The Add Movie Button" instead of "Label=Add".
This is OK for demonstration purposes but reasonably limited on its own. For testing you probably want to try to use it in combination with TextTest
. Also, you can examine the extra features such as synchronisation support via Application Events
, macro recording with GUI shortcuts
, and recording and playing back received signals