Thursday, May 29, 2008

Drive TabControl through Windows UI Automation

To automate UI testing, UI Automation classes have been added to the .net class arsenal (.net 3.0 and 3.5).

I have been playing with System.Windows.Automation since last week.

So here is what I had achieved so far.. 1. Launch an application (simplest)
2. Identify a button and click it
3. Identify a Tab Control and switch tab

Prerequisites:
A. .net 3.x framework
B. UISpy (hard to get now a days, will post the link)
C. Adding reference to UIAutomationClient.dll
(Located at X:\Program Files\Reference Assemblies\Microsoft\Framework\v3.x)

Setting up:
1. Fireup Visual Studio 2005/8 with .net 3.x installed
2. Create a new forms app project
3. Add refernce to UIAutomationClient.dll and System.Threading

Process:
1. To achieve automation goals, you start with capturing entire desktop then identifying the form/window you would be dealing with

2. The captured desktop forms the root of control tree which automation framework would interact to perform actions on UI controls

3. Major classes/enums of interest are as under:

3a. AutomationElement:
http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.aspx

3b. TreeScope:
http://msdn.microsoft.com/en-us/library/system.windows.automation.treescope.aspx

3c. PropertyCondition
http://msdn.microsoft.com/en-us/library/system.windows.automation.propertycondition.aspx

3d. InvokePattern
http://msdn.microsoft.com/en-us/library/system.windows.automation.invokepattern.aspx

Now some code:
Fireup the application under (UI) test:

Process aut = Process.Start("Path to the app under test");

// Capture whatever you have on desktop
AutomationElement aeDesktop = AutomationElement.RootElement;

// Spot AUT in the crowd
// Must put win form title in place of "WINDOW TITLE HERE" with quotes
AutomationElement aeForm =
aeForm = aeDesktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "WINDOW TITLE HERE"));

// Find a tabControl in AUT
// AutomationIdProperty is the programmatic name which was assigned to the tab
// control by the app developer. To find AutomationIdProperty use UISpy

AutomationElement aeTabControl = aeForm.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty,"tabControl1"));

// Set focus on the tab control referenced by AutomationElement object
aeTabControl.SetFocus();

// Time to switch to another Tab in tabControl identified in previous step
// A tabControl with multiple pages would have title for each page
// You must pass the page title to ProperyCondition method

AutomationElement aeTabPage = aeTabControl.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "TAB PAGE TITLE HERE"));

SelectionItemPattern changeTab_aeTabPage = aeTabPage.GetCurrentPattern(SelectionItemPattern.Pattern) as SelectionItemPattern;

changeTab_aeTabPage.Select();

// Time to point and shoot (click) a Button
// Must provide the text that appears on button to PropertyCondition
AutomationElement aeBtnClose = aeForm.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "TEXT ON BUTTON"));

aeBtnClose.SetFocus();

// Click the button using InvokePattern
InvokePattern click_aeBtnClose = (InvokePattern)aeBtnClose.GetCurrentPattern(InvokePattern.Pattern);

click_aeBtnClose.Invoke();



Summary:
This sample drives a tabControl and a button through automation classes in System.Windows.Automation namespace. I will update this code as I explore things further... comments good/bad/ugly are welcome.. no spam and bots pls..