Strongwind

Strongwind is a GUI test automation framework inspired by dogtail. Strongwind is object-oriented and extensible. You can use Strongwind to build object-oriented representations of your applications ("application wrappers"), then reuse the application wrappers to quickly develop many test scripts. Strongwind scripts generate a human-readable log that contains the action, expected result and a screen shot of each step. Most simple actions are logged automatically.

Strongwind is written in Python and uses the pyatspi library to manipulate and query the state of applications. Strongwind automatically classifies widgets by their ATK role and provides implementations for common actions on regular widgets — for example, selecting an item in a menu or asserting that a window has closed — but you can extend Strongwind's implementations or add your own implementations for custom widgets to handle alternate behaviors or custom widgets in your applications.

  • Language: Python
  • License: GPL
  • Latest Version: 0.9, Download

Quick Links

Recent Blog Posts

When using Python to do some accessibility work using pyatspi, it's very handy to have the documentation available for the classes and methods available. One way to inspect them is as follows.

 

Start Python's interpreter:

 

joe@itaca:~$ python
Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

 

 

While running Python's interpreter, import the pyatspi module:

 

>>> import pyatspi

 

Inspect the symbols in that module:

 

>>> dir(pyatspi)

 

You should get a pretty big list of elements, something like:

['ALL_INTERFACES', 'Accessibility', 'Accessibility__POA', 'CACHE_EVENTS', 'CACHE_INTERFACES', 'CACHE_PROPERTIES', 'DESKTOP_COORDS', 'EVENT_TREE', 'KEY_PRESS', 'KEY_PRESSED', 'KEY_PRESSED_EVENT', 'KEY_PRESSRELEASE', 'KEY_RELEASE', 'KEY_RELEASED', 'KEY_RELEASED_EVENT', 'KEY_STRING', 'KEY_SYM', 'LAYER_BACKGROUND', 'LAYER_CANVAS', 'LAYER_INVALID', 'LAYER_LAST_DEFINED', 'LAYER_MDI', 'LAYER_OVERLAY', 'LAYER_POPUP', 'LAYER_WIDGET',

 

 

If the list like above appeared, it means you have pyatspi installed and everything is fine. Now we need to iterate those symbols and request their help documentation.

 

>>> for label in dir(pyatspi):
...     help(label)
... 
 

 

And the docs should be displayed on the screen. An example of the format in which the documentation is:

 

    class Text(Bonobo.Unknown)
     |  Method resolution order:
     |      Text
     |      Bonobo.Unknown
     |      CORBA.Object
     |      __builtin__.object
     |  
     |  Methods defined here:
     |  
     |  addSelection(...)
     |      addSelection(startOffset, endOffset) -> 'IDL:omg.org/CORBA/boolean:1.0'
     |  
     |  getAttributeRun(...)
     |      getAttributeRun(offset, includeDefaults) -> 'IDL:Accessibility/AttributeSet:1.0', startOffset, endOffset
     |  
     |  getAttributeValue(...)
     |      getAttributeValue(offset, attributeName) -> 'IDL:omg.org/CORBA/string:1.0', startOffset, endOffset, defined
     |  
     |  getAttributes(...)
     |      getAttributes(offset) -> 'IDL:omg.org/CORBA/string:1.0', startOffset, endOffset
     |  
     |  getBoundedRanges(...)
     |      getBoundedRanges(x, y, width, height, coordType, xClipType, yClipType) -> 'IDL:Accessibility/Text/RangeList:1.0'
     |  
     |  getCharacterAtOffset(...)
     |      getCharacterAtOffset(offset) -> 'IDL:omg.org/CORBA/unsigned_long:1.0'
     |  
     |  getCharacterExtents(...)
     |      getCharacterExtents(offset, coordType) -> 'IDL:omg.org/CORBA/void:1.0', x, y, width, height
     |  
     |  getDefaultAttributeSet(...)
     |      getDefaultAttributeSet() -> 'IDL:Accessibility/AttributeSet:1.0'
     |  
     |  getDefaultAttributes(...)
     |      getDefaultAttributes() -> 'IDL:omg.org/CORBA/string:1.0'
     |  
     |  getNSelections(...)
     |      getNSelections() -> 'IDL:omg.org/CORBA/long:1.0'
     |  
     |  getOffsetAtPoint(...)
     |      getOffsetAtPoint(x, y, coordType) -> 'IDL:omg.org/CORBA/long:1.0'
     |  
     |  getRangeExtents(...)
     |      getRangeExtents(startOffset, endOffset, coordType) -> 'IDL:omg.org/CORBA/void:1.0', x, y, width, height
     |  
     |  getSelection(...)
     |      getSelection(selectionNum) -> 'IDL:omg.org/CORBA/void:1.0', startOffset, endOffset
     |  
     |  getText(...)
     |      getText(startOffset, endOffset) -> 'IDL:omg.org/CORBA/string:1.0'
     |  
     |  getTextAfterOffset(...)
     |      getTextAfterOffset(offset, type) -> 'IDL:omg.org/CORBA/string:1.0', startOffset, endOffset
     |  
     |  getTextAtOffset(...)
     |      getTextAtOffset(offset, type) -> 'IDL:omg.org/CORBA/string:1.0', startOffset, endOffset
     |  
     |  getTextBeforeOffset(...)
     |      getTextBeforeOffset(offset, type) -> 'IDL:omg.org/CORBA/string:1.0', startOffset, endOffset
     |  
     |  removeSelection(...)
     |      removeSelection(selectionNum) -> 'IDL:omg.org/CORBA/boolean:1.0'
     |  
     |  setCaretOffset(...)
     |      setCaretOffset(offset) -> 'IDL:omg.org/CORBA/boolean:1.0'
     |  
     |  setSelection(...)
     |      setSelection(selectionNum, startOffset, endOffset) -> 'IDL:omg.org/CORBA/boolean:1.0'
     |  
     |  unImplemented(...)
     |      unImplemented() -> 'IDL:omg.org/CORBA/void:1.0'
     |  
     |  unImplemented2(...)
     |      unImplemented2() -> 'IDL:omg.org/CORBA/void:1.0'
     |  
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |  
     |  caretOffset
     |  
     |  characterCount
     |  
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |  
     |  Range = <class 'Accessibility.Range'>
     |  
     |  
     |  __typecode__ = <CORBA.TypeCode 'IDL:Accessibility/Text:1.0'>
     |  
     |  ----------------------------------------------------------------------
     |  Methods inherited from Bonobo.Unknown:
     |  
     |  queryInterface(...)
     |      queryInterface(repoid) -> 'IDL:Bonobo/Unknown:1.0'
     |  
     |  ref(...)
     |      ref() -> 'IDL:omg.org/CORBA/void:1.0'
     |  
     |  unref(...)
     |      unref() -> 'IDL:omg.org/CORBA/void:1.0'
     |  

 

 

 

I am adding the document with all the API docs as an attachment.

0 Comments Permalink

Brian Merrell just posted on his blog that the Mono UI Automation team is using Strongwind to test their Mono WinForms accessibility implementation.  Brian's also written a document that covers Strongwind Basics on the Mono web site.  It's a good supplement to the Getting Started with Strongwind document I wrote for Strongwind's initial release.

 

Thanks, Brian!

 

0 Comments 0 References Permalink

Actions

Notifications

Getting Started

There are two main documents that cover Strongwind for beginners: