2014-09-17

MS UI Automation是什么

UIA架构

UI自动化模型

  UI自动化树概述

  UI自动化控件模式概述

  UI 自动化属性概述

  UI 自动化事件概述

示例

  使用UISpy工具

UI自动化提供者

常见问题分析解决

  控件无法识别

  Timing issue

  本地化问题

自动化技术和自动化框架

参考

MS UI Automation是什么[1]


 返回

UI Automation 就是用另一个程序来控制UI 程序,模拟用户操作。他包含三步骤:

  1. 找到UI 元素
  2. 模拟用户操作
  3. 检查UI属性和行为

微软UI Automation技术提供了很好的实现模型。简单来讲,它就是几个dll,提供了一套API及其相应的模式,让软件的开发者遵循该模式去实现相应的interface,从而使测试人员更方便的编写UI Automation。 

UIA架构[1]


 返回

MS UIA明确定义了两个role:UIA Provider即软件本身,也可称为服务器端,UIA Client即自动化脚本和相关的assistive technology applications,见图1。

  • UIA Provider: 开发人员确定控件行为并实现对应的UIA control pattern(注意:对于标准控件而言,默认是支持UIA的,而对于自定义的控件,需要实现该控件的行为对应于UIA所定义的interface。)
  • UIA Client:相对而言,UIA Client则简单了很多,只需调用相关的UIA API去完成自动化测试脚本。

MS UI Automation Introduction

图1 架构简易图

 

MS UI Automation Introduction

图2 官方架构图

在图2中,Applications是软件本身,也可成为服务器端,Accessibility Tool是客户端,即测试软件或测试工具(如UISpy.exe)。

从图2可得知UIAutomation Core是通信基础代码,而且Applications和Accessibility Tool是通过管道通信的。

UIA主要有4个组件

组件                                       

                           

提供程序 API(UIAutomationProvider.dll 和 UIAutomationTypes.dll)                                       

定义了各种行为的interface,例如,假设有个自定义的控件,开发人员觉得它需要支持Dock行为,就需要实现IDockProvider接口。            

客户端 API(UIAutomationClient.dll 和 UIAutomationTypes.dll)                                       

定义了各种控件模式,以及一些用来支持更好的定位控件的辅助条件搜索类                                  

UiAutomationCore.dll                                       

处理提供程序与客户端之间的通信的基础代码(有时也称为 UI 自动化核心)。                                       

UIAutomationClientsideProviders.dll                                       

一组用于标准旧版本控件的 UI 自动化提供程序。(WPF 控件为 UI 自动化提供本机支持。)此支持自动提供给客户端应用程序。                    

MS UI Automation Introduction

图3 UIA dll 使用

常用命名空间:

namespace                                          

引用的 DLL                                       

读者                                       

System.Windows.Automation                                       

UIAutomationClient;UIAutomationTypes                                       

AutomationElement 对象、注册 UI 自动化事件以及与 UI 自动化控件模式一起使用。                                       

System.Windows.Automation.Provider                                       

UIAutomationProvider;UIAutomationTypes                                       

除 WPF 之外的框架的 UI 自动化提供程序开发人员。                                       

System.Windows.Automation.Text                                       

UIAutomationClient;UIAutomationTypes                                       

除 WPF 之外的框架的 UI 自动化提供程序开发人员;用于实现 TextPattern 控件模式。                                       

System.Windows.Automation.Peers                                       

PresentationFramework                                       

WPF 的 UI 自动化提供程序开发人员。

UI自动化模型[2]


 返回

UI 自动化将 UI 的每一部分作为一个 AutomationElement 向客户端应用程序公开。 

元素包含在树结构中,以桌面作为根元素。

AutomationElement 对象公开它们所表示的 UI 元素的通用属性。  其中一个属性是控件类型,它将其基本外观和功能定义为一个可识别的实体:例如按钮或复选框。

此外,元素还公开控件模式,以提供特定于这些元素的控件类型的属性。  控件模式还公开方法,使客户端能够获取有关元素的进一步信息并提供输入。

注意:控件类型和控件模式之间并不是一一对应的关系。  多个控件类型可以支持同一个控件模式,一个控件可以支持多个控件模式,每个控件模式公开其行为的不同方面。 例如,一个组合框至少具有两个控件模式:一个表示其展开和折叠功能,另一个表示选择机制

UI 自动化还通过事件向客户端应用程序提供信息。  与 WinEvent 不同的是,UI 自动化事件并不基于广播机制。 UI 自动化客户端注册特定的事件通知,并且可以请求将特定的 UI 自动化属性和控件模式信息传入其事件处理程序中。 此外,UI 自动化  事件包含到引发该事件的元素的引用。 提供程序可以通过有选择地引发事件来改善性能,具体取决于所有客户端是否在侦听。 

UI自动化树概述[3]

在UIA中,程序UI的每一个部分都被认为是一个AutomationElement类,他们是一个树状的结构,Desktop被认为是每个windows based app的UIA树状图的根,从类的定义中,我们也可以看到一个AutomationElement类中有一个static的RootElement属性。

该树的结构中,一共有3中View Model,分别为Raw View, Control View和Content View:

Raw View提供的信息最多,也是其他view的基础,最贴近于程序本身的编程结构;

Control View是Raw View的子集,它最贴近于最终用户所能感知的UI结构,但是它不包含不能和用户相互交互的一些UI,例如listview的header,toolbar等等;

Content View则是Control View的一个子集,它只包含能和用户直接交互真实信息的控件,比如接受键盘输入的Textbox,选择不同值的Combobox;而诸如lable等控件则不会包含在其中。

UI自动化控件模式概述[4]

控件模式需实现定义控件中可用的一项独立功能所需的方法、属性、事件和关系: 

  • UI 自动化元素与其父元素、子元素以及同级元素之间的关系描述了 UI 自动化树内元素的结构。 
  • UI 自动化客户端使用方法可以操作控件。 
  • 属性和事件提供了有关控件模式功能的信息以及有关控件状态的信息。

UIA大概一共定义了38种pattern,代表了常用的控件行为,他们也会提供一些具体的功能性的属性。

  • 对于UIA Provider来说,所做的事情就是定义控件相关的行为,找到该行为对应的模式,并实现该模式;
  • 对于client而言,即访问相关的方法和属性,来实现自动化。

如某个控件需要有InvokePattern,则provider和client相对应的则为:

控件模式类 (Client)                                      

提供程序接口(Provider)                                      

说明                                       

                InvokePattern

       IInvokeProvider              

用于可被调用的控件,如按钮。

 

UI 自动化属性概述[5]

每个property都由一个数字和名字来标识,provider用数字ID来确定属性请求(出于安全原因,UI 自动化提供程序将从 Uiautomationtypes.dll 中包含的一组单独的类中获取这些对象。);而client则用AutomationProperty类获取具体的某一属性的内容。

UI 自动化事件概述[6]

UIA是采用订阅模型,而不是以前的广播事件模型。定义了四种事件类型:Property change,Element action,Structure change和Global desktop change。

客户端的 UI 自动化事件

示例[8]


 返回

下面这个示例用测试程序完成以下操作:

  1. 打开Calculater.exe;
  2. 找到button '3', '+', '5', '-', '2', '=', 并模拟点击它们。这样,计算器屏幕上会显示‘3+5-2’,并计算结果;
  3. 找到计算器屏幕,得到计算结果;
  4. 比较计算结果和预期结果是否一致。一致,则pass;反之,则fail。
  1 //Reference UIAutomationClient and UIAutomationTypes
  2 
  3 using System;
  4 using System.Windows.Automation;
  5 using System.Windows;
  6 
  7 namespace CalcClient
  8 {
  9     class CalcAutomationClient
 10     {
 11         AutomationElement calcWindow = null; //Main UI Window element
 12         //The following ID can be obtained from tool: UI Spy     
 13         string resultTextAutoID = "150"; //ID for Text element of output window
 14         string btn5AutoID = "135"; //ID for button 5
 15         string btn3AutoID = "133"; // ID for button 3
 16         string btn2AutoID = "132"; // ID for button 2
 17         string btnPlusAutoID = "93"; // ID for button +
 18         string btnSubAutoID = "94"; // ID for button -
 19         string btnEqualAutoID = "121"; // ID for button =
 20 
 21         static void Main(string[] args)
 22         {
 23             CalcAutomationClient autoClient = new CalcAutomationClient();
 24 
 25             //Create callback for new Window open event. Test should run only when the main Window shows.
 26             AutomationEventHandler eventHandler = new AutomationEventHandler(autoClient.OnWindowOpenOrClose);
 27             //Attach the event with desktop element and start listening.
 28             Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, eventHandler);
 29 
 30             //Start caculator. When new window opens, the new window open event should fire.
 31             System.Diagnostics.Process.Start("calc.exe");
 32 
 33             //Wait execution
 34             Console.ReadLine();
 35         }
 36 
 37         void OnWindowOpenOrClose(object src, AutomationEventArgs e)
 38         {
 39             if (e.EventId != WindowPattern.WindowOpenedEvent)
 40             {
 41                 return;
 42             }
 43 
 44             AutomationElement sourceElement;
 45 
 46             try
 47             {
 48                 sourceElement = src as AutomationElement;
 49 
 50                 //Check the event source is caculator or not.
 51                 //In production code, string should be read from resource to support localization testing.
 52                 if (sourceElement.Current.Name == "Calculator")
 53                 {
 54                     calcWindow = sourceElement;
 55                 }
 56             }
 57             catch (ElementNotAvailableException)
 58             {
 59                 return;
 60             }
 61 
 62             //Start testing
 63             ExecuteTest();
 64         }
 65 
 66         void ExecuteTest()
 67         {
 68             //Execute 3+5-2
 69             //Invoke ExecuteButtonInvoke function to click buttons
 70             ExecuteButtonInvoke(btn3AutoID);
 71             ExecuteButtonInvoke(btnPlusAutoID);
 72             ExecuteButtonInvoke(btn5AutoID);
 73             ExecuteButtonInvoke(btnSubAutoID);
 74             ExecuteButtonInvoke(btn2AutoID);
 75             System.Threading.Thread.Sleep(1000);
 76             ExecuteButtonInvoke(btnEqualAutoID);
 77 
 78             //Invoke GetCurrentResult function to read caculator output
 79             if (GetCurrentResult() == "6")
 80             {
 81                 Console.WriteLine("Execute Pass!");
 82                 return;
 83             }
 84 
 85             Console.WriteLine("Execute Fail!");
 86         }
 87 
 88         void ExecuteButtonInvoke(string automationID)
 89         {
 90 
 91             //Create query condition object, there are two conditions.
 92             //1. Check AutomationID
 93             //2. Check Control Type
 94             Condition conditions = new AndCondition(
 95                 new PropertyCondition(AutomationElement.AutomationIdProperty, automationID),
 96                  new PropertyCondition(AutomationElement.ControlTypeProperty,
 97                                  ControlType.Button));
 98 
 99             AutomationElement btn = calcWindow.FindAll(TreeScope.Descendants, conditions)[0];
100 
101             //Obtain the InvokePattern interface
102             InvokePattern invokeptn = (InvokePattern)btn.GetCurrentPattern(InvokePattern.Pattern);
103 
104             //Click button by Invoke interface
105             invokeptn.Invoke();
106         }
107 
108         string GetCurrentResult()
109         {
110 
111             Condition conditions = new AndCondition(
112                 new PropertyCondition(AutomationElement.AutomationIdProperty, resultTextAutoID),
113                  new PropertyCondition(AutomationElement.ControlTypeProperty,
114                                  ControlType.Text));
115 
116             AutomationElement btn = calcWindow.FindAll(TreeScope.Descendants, conditions)[0];
117 
118             //Read name property of Text control. The name property is the output.
119             return btn.Current.Name;
120         }
121     }
122 }
View Code

相关文章:

  • 2022-12-23
  • 2022-01-21
  • 2021-11-20
  • 2021-10-20
  • 2022-02-28
  • 2022-12-23
猜你喜欢
  • 2021-06-25
  • 2022-12-23
  • 2022-12-23
  • 2021-08-02
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案