DogtailTutorial

Differences between revisions 1 and 2
Revision 1 as of 2008-01-09 18:26:52
Size: 1643
Editor: a91-154-119-10
Comment: First draft of dogtail tutorial.
Revision 2 as of 2008-01-09 18:39:02
Size: 3638
Editor: a91-154-119-10
Comment: Additional material for the dogtail tutorial.
Deletions are marked like this. Additions are marked like this.
Line 8: Line 8:
 1. Read /usr/share/python-support/python-dogtail/dogtail/procedural.py to have a feeling for the API.  1. Read /usr/share/python-support/python-dogtail/dogtail/procedural.py to have a feeling for the API. (It's somewhat tricky Python code, though.)

Some notes on the dogtail API:

 * run("programname") runs a GUI program and waits until it has opened a window.
 * focus.application("windowname") chooses a top-level. Despite the name, this does not actually change the focus in the application, just a pointer inside the dogtail library.
 * focus.text() chooses a text editing widget.
 * There are a bunch of other such helper functions, see procedural.py for info.
 * focus(name="foo", roleName="bar", description="foobar") is the real way to choose widgets, which the above helpers call, in most cases (though not all). You get the name, roleName, and description values from dogtail-sniff (see below). You only need to specify the one or ones you want to, but you need at least one.
 * In all cases, when choosing a widget, dogtail uses heuristics. Sometimes this fails. For example, Gedit has a widget called "Save" in at least two places: the toolbar in the main window, plus a button in the "Save as..." dialog. To work around this, you may need to choose a parent widget first: dogtail seems to prefer to find children of the currently chosen widget.
 * click("name") performs the "click" action on a widget, which is first chosen; arguments are same as for focus(). Clicking does not work for widgets, but it does for work those for which it is natural, such as buttons.
 * click("name") also seems to work for menu items.
 * type("text") pretends the user is typing the given text.

Additional notes:

 * dogtail-sniff lets you browse the widgets of other, running programs. This is how you figure out the names to give to the API to search for them. Note that the names must be exact, and that copy-paste is sometimes the only reliable way of getting them right (especially with silly Unicode ellipsis characters, as in the example below).
 * When you click on a widget in dogtail-sniff, it gets briefly highlighted in the actual window. Be prepared, or you'll miss it.

A quick tutorial on using dogtail, on Ubuntu gutsy.

  1. Install GNOME, if you don't have it already.
  2. Enable accessibility features: System -> Settings -> Accessibilty, then click on the "enable" tick.

  3. Log out and back in. The accessibility features won't be enabled until after you do this.
  4. Install the python-dogtail package.
  5. Run the script below with "python gedit.py".
  6. Read /usr/share/python-support/python-dogtail/dogtail/procedural.py to have a feeling for the API. (It's somewhat tricky Python code, though.)

Some notes on the dogtail API:

  • run("programname") runs a GUI program and waits until it has opened a window.
  • focus.application("windowname") chooses a top-level. Despite the name, this does not actually change the focus in the application, just a pointer inside the dogtail library.
  • focus.text() chooses a text editing widget.
  • There are a bunch of other such helper functions, see procedural.py for info.
  • focus(name="foo", roleName="bar", description="foobar") is the real way to choose widgets, which the above helpers call, in most cases (though not all). You get the name, roleName, and description values from dogtail-sniff (see below). You only need to specify the one or ones you want to, but you need at least one.
  • In all cases, when choosing a widget, dogtail uses heuristics. Sometimes this fails. For example, Gedit has a widget called "Save" in at least two places: the toolbar in the main window, plus a button in the "Save as..." dialog. To work around this, you may need to choose a parent widget first: dogtail seems to prefer to find children of the currently chosen widget.
  • click("name") performs the "click" action on a widget, which is first chosen; arguments are same as for focus(). Clicking does not work for widgets, but it does for work those for which it is natural, such as buttons.
  • click("name") also seems to work for menu items.
  • type("text") pretends the user is typing the given text.

Additional notes:

  • dogtail-sniff lets you browse the widgets of other, running programs. This is how you figure out the names to give to the API to search for them. Note that the names must be exact, and that copy-paste is sometimes the only reliable way of getting them right (especially with silly Unicode ellipsis characters, as in the example below).
  • When you click on a widget in dogtail-sniff, it gets briefly highlighted in the actual window. Be prepared, or you'll miss it.

Sample program to do a simple Gedit test (save as gedit.py):

# coding=utf-8

# A small sample script for dogtail. Starts Gedit, inserts some text,
# saves it, quits Gedit, and verifies that the saved file is correct.

import os
import shutil
import tempfile

from dogtail.procedural import *

os.environ["LC_ALL"] = "C"

dirname = tempfile.mkdtemp()
filename = os.path.join(dirname, "hello.txt")
string = "hello, world"

run("gedit")

focus.application("gedit")
focus.text()
type(string)

click("Save")
focus.text()
type(filename)
focus.widget(name="Save As…", roleName="dialog")
click.button("Save")
# At this point we have what is technically called a race condition.
# The save might not have happened by the time click.button() returns,
# and so we might be quitting too early. On my desktop machine it is
# fast enough, inside qemu not.

click("Quit")

saved_string = file(filename).read()
if saved_string != string + "\n": # gedit adds a newline to the end, always!
    print "error: bad content saved"
    print repr(saved_string)
else:
    print "ok"

shutil.rmtree(dirname)

Testing/Automation/DogtailTutorial (last edited 2008-08-06 17:01:14 by localhost)