Saturday, May 16, 2009

Pycon 2009: Functional Testing of Desktop Applications

Here is a link to Michael Foord talk at Pycon 2009 in Chicago about functional testing of desktop applications:

Functional Testing of Desktop Applications
Many advocates of unit testing believe that testing desktop (GUI) applications is so difficult as to not be worth it. Not only is it possible, but 'functional testing' (testing an application from the point of view of the user) is an important part of an agile development process.

I watched it yesterday and it is very good!

Friday, May 15, 2009

Testing an unknown application

From time to time you may need to test an unknown application. I have encounter it when I needed to test our installation program. The task was simple - install the application for automated smoke tests. In such cases I gladly return to Accessibility.

Let's pretend our testing application is not written in .NET and the only way how to explore it is through the accessibility (AccExplorer):

All we need to do is to access Accessibility objects from IronPython. There is a project called Managed Windows API that nicely wraps accessibility for .NET. It also wraps other Win32 API calls (mouse clicks etc.) but I stay with Win32API.dll because of my laziness :-).

Utilizing the Managed Windows API you can control the accessibility objects. Here is the snippet:

import clr
# Win32API provide access to Win32 API functions
clr.AddReference('Win32API')
from Win32API import Win32API
# ManagedWinapi provide access to Accessibility objects
clr.AddReference('ManagedWinapi')
import ManagedWinapi.Accessibility as ma
import ManagedWinapi.Windows as mw

def GetGUIATWindow():
   """ Return GUIAT_PoC window accessibility object. """
   def callback(aWindow):
       return aWindow.Title == 'GUIAT - Proof of Concept'
   guiat_window = mw.SystemWindow.FilterToplevelWindows(callback)
   # assume guiat_window is list with just one object
   return ma.SystemAccessibleObject.FromWindow(guiat_window[0],
       ma.AccessibleObjectID.OBJID_WINDOW)

guiat_acc = GetGUIATWindow()
# position of the 'New listbox item' text box
pos = guiat_acc.Children[3].Children[1].Location
# focus the text box
Win32API.MouseClick(pos.X + pos.Width/2, pos.Y + pos.Height/2)
Win32API.SendString('Accessibility test')
# position of the 'Add Item' button
pos = guiat_acc.Children[3].Children[2].Location
# click the button
Win32API.MouseClick(pos.X + pos.Width/2, pos.Y + pos.Height/2)

To run it, download managedwinapi-0.3.zip and extract the ManagedWinapi.dll to the same folder as the source code.

When you run the code, it enters Accessibility test text into New listbox item text box and clicks Add Item button. The controls are always on the same position within the Children enumeration so we can use direct referencing: e.g. guiat_acc.Children[3].Children[2] is the button accessibility object.

Enhancing this example is up to you - I have created several functions that take care about entering the text into text boxes, selecting buttons or a checking check boxes. That's all I need to create a script that installs our application.