MS UI Automation Introduction

MS UI Automation Introduction

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去完成自动化测试脚本。

图1 架构简易图

图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 自动化提供本机支持。)此支持自动提供给客户端应用程序。

图3 UIA dll 使用

常用命名空间:


namespace


引用的 DLL


读者


System.Windows.Automation


UIAutomationClient;UIAutomationTypes


UI 自动化客户端开发人员;用于查找 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。

示例[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 }

使用UISpy工具

UISpy可以当作Client,找到Server所提供的属性、控件模式,也可对Server进行模拟操作。

图4 UISpy attached to Calculator

UI自动化提供者

在UIA架构中提到:对于标准控件而言,默认是支持UIA的,而对于自定义的控件,需要实现该控件的行为对应于UIA所定义的interface。

这里提到的实现UIA所定义的interface,就是UIA provider。UIA provider可在根据实际情况在服务器端和客户端实现,示例如下:

客户端:

Client-Side UI Automation Provider -  WinForm Sample

服务器端:

Server-Side UI Automation Provider - WinForm Sample

Server-Side UI Automation Provider - WPF Sample

常见问题分析解决[8]



返回

控件无法识别

  1. 如果是因为自动化测试工具的限制,比如对于WinForm的控件,有些自动化工具就不能识别,碰到这种情况,最好是看这个工具有没有扩展可以用,比如Silktest的.Net Framework扩展。如果不行,那只能换自动化测试工具了。所以这个凸显出在做自动化测试以前,选择自动化测试工具的重要性。
  2. 如果是因为控件比较复杂,自动化工具可以识别,但是无法操作。这时我们可以通过Window API以及消息的方式来做,比如自己去调Window API来操作窗口,或者请开发实现一下消息的接口来给自动化工具调用等
  3. 跟开发沟通,让他们的控件支持IAccessible接口,然后我们通过MSAA来操作(如果是WPF控件,则需要实现UIAutomation定义的一些接口)。不过一般情况下,除了微软这样对软件的Accessible要求很高的公司,其它公司很少会花费时间来实现这个接口……。 另外扯一句,产品的Accessible的程度,实质上决定了一个公司能对产品做自动化测试的程度。
  4. 如果以上方法都不行,那只有最后一个双刃剑可以用了,就是鼠标键盘模拟。理论上来说,只要用户可以操作的东西,只要有界面,就可以通过鼠标键盘模拟来实现(君不见N多游戏外挂的键盘鼠标模拟大法)。就如双刃剑一样,这种做法是杀敌一千,自损八百。因为鼠标键盘模拟非常依赖于当前激活的窗口以及光标位置和焦点位置,而且同步起来很困难。这也造成了后期维护成本很高。

Timing issue

提倡第一种方法。

  1. Waiter/EventDriven
  2. Retry sleep a small interval value
  3. Thread.Sleep a long time

本地化问题

Avoid localize issue, read resource string

自动化技术和自动化框架[8]



返回

前面提到了UIA作为全新UI自动化测试技术的优势,但这并不能解决所有的UI 自动化问题。 自动化框架正是为了自动化技术没有完全解决的问题。比如:

  • 自动化中的同步和等待。 对于稍复杂的UI 程序,测试程序往往需要根据测试目标的状态决定 下一步的操作。 比如测试文件另存为功能的时候,若保存路径是网络路径,可能会因为网络延迟导致整个UI停顿比较长的时间。这个时候测试,程序如果不顾当前状态而简单地执行下一步操作,比如新建文件, 很可能会因为UI延迟而失败。 正确的做法是,测试程序应该等待文件保存成功返回后,再进行下一步操作。 这就是自动化中同步和等待的一个例子。实现同步和等待有多种方法,最简单粗暴的做法是硬编码一个长时间的 Sleep在测试代码中。 稍微好一点的做法可以采取小时间片的轮询状态检查, 或者反复重试。 借助 UIA的Event Pattern,可以尝试捕获另存为窗口的关闭WindowClosedEvent。 如果要做得完善一点, 可以把多种方法结合, 另外再额外检查目标程序的CPU使用情况,消息循环是否有回应,设定超时时间等等。
  • 冗繁的编码过程。 对于一个UI窗口,里面可能有几十个子控件或者子窗口。 在编写测试代码的时候, 如果对这些子元素的获取,操作不能简化, 势必导致代码冗繁,难以维护。 借助自动代码生成和ORM (Object Role Modeling)等技术, 可以解决这个问题。 比如可以用工具把窗口及其子元素的关系和搜索条件都序列化到XML文件中, 然后采用ORM技术即可在代码中轻松获取子元素。
  • 多语言和本地化测试。多语言和本地化的测试对UI来说显得尤为重要。 UI程序往往通过资源文件来定义所显示的内容, 这就要求自动化测试要可以方便读取和定位程序的资源文件, 来支持多语言和本地化测试。
  • 支持工具和辅助函数的匮乏。 对于大的项目研发, 通过好的工具来减小开发成本是非常必要的。 就UI自动化来说, 如果自动化测试用例可以通过一次录制,多次播放来做的话,成本会减少很多。 在VS2010中就提供了这样的录制-播放功能。 详细视频可以参考How to create record and playback Test Cases in Visual Studio Beta2。
  • 区分功能性测试和用户真实行为模拟。 前面提到, 就点击按钮功能来说, 可以通过SendKey来模拟鼠标操作, 或者通过Windows Message来直接触发点击事件。 这两种不同方法各有优劣。 比如当按钮被其它元素遮挡, 通过SendKey进行模拟就会导致失败,而直接发送Windows Message还是会成功。 孰优孰劣取决于要达到的目的。 如果单纯为了测试按钮点击后导致的结果,通过Windows Message来模拟就省去了很多麻烦。 相反, 如果是界面测试, 通过SendKey来模拟就可以让按钮被遮挡的bug暴露出来, 而Windows Message则不能发现这样的问题。

所以,单纯的某个自动化技术或者方法也无法满足需求。为了解决上述问题,各种自动化测试框架逐渐涌现和发展。微软内部有多个不同的自动化框架,设计理念和侧重点各有不同。 Visual Studio 2010将加入对自动化测试的支持。 在CodePlex上面, 也可以找到多种框架,比如White和UI Automation Verify。

参考

[1] MS UI Automation简介

[2] UI 自动化概述

[3] UI 自动化树概述

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

[5] UI 自动化属性概述

[6] UI 自动化事件概述

[7] 使用 UI 自动化进行自动化测试

[8] UI Automation - under the hood

时间: 2024-10-06 09:43:14

MS UI Automation Introduction的相关文章

MS UI Automation简介

转自:http://blog.csdn.net/ffeiffei/article/details/6637418 MS UI Automation(Microsoft User Interface Automation:UIA)是随.net framework3.0一起发布的,虽然在如今这个几乎每天都有各种新名词.新技术出来的所谓的21世纪,它显得已经有些过时了.前些日子,正好一个项目,可以用到它,又重新整理了一下: 什么是MS UI Automation MS UI Automation是MS

UI Automation 简介

转载,源地址: http://blog.csdn.net/ffeiffei/article/details/6637418 MS UI Automation(Microsoft User Interface Automation:UIA)是随.net framework3.0一起发布的,虽然在如今这个几乎每天都有各种新名词.新技术出来的所谓的21世纪,它显得已经有些过时了.前些日子,正好一个项目,可以用到它,又重新整理了一下: 什么是MS UI Automation MS UI Automati

UI Automation

Introduction UI Automation是Microsoft .NET 3.0框架下提供的一种用于自动化测试的技术,是在MSAA基础上建立的,MSAA就是Microsoft Active Accessibility.UI Automation在某些方面超过了MSAA,UI自动化提供了Windows Vista中,微软Windows XP的全部功能,和Windows Server 2003. 在UI Automation中,所有的窗体.控件都表现为一个AutomationElement

使用UI Automation实现自动化测试--5-7

使用UI Automation实现自动化测试--5 (Winfrom和WPF中弹出和关闭对话框的不同处理方式) 在使用UI Automation对Winform和WPF的程序测试中发现有一些不同的地方,而这些不同来自于Winform与WPF的处理机制不同.下面我们通过一个简单的实例来加以说明: 实例描述 我们使用InvokePattern来点击按钮弹出一个对话框,然后点击对话框中的“确定”按钮关闭对话框. 两种方式对比 首先我们使用如下代码来针对Winfom和WPF分别进行测试: 1public

iOS instruments之ui automation的简单使用(高手绕道)

最近使用了几次instruments中的automation工具,现记录下automation的简单使用方法,希望对没接触过自动化测试又有需求的人有所帮助.  UI 自动测试是iOS 中重要的附加功能,它由名为"Automation"的新的工具对象支持.Automation工具的脚本是用JavaScript语言编写,主要用于分析应用的性能和用户行为,模仿/击发被请求的事件,利用它可以完成对被测应用的简单的UI测试及相关功能测试. 一. 简单的录制脚本 打开xcode,这里用我为我家亲爱

关于UI Automation框架

微软提供的UI Automation框架给开发windows平台的自动化测试带来了很大的便利,这里就总结一下相关的代码. 首先,直接使用UI Automation框架,完成一个NotePad的about窗口中的 “OK” button的点击: 1 AutomationElement root = AutomationElement.RootElement; 2 AutomationElement about_notepad_windows = root.FindFirst( 3 TreeScop

基于UI Automation的自动化测试框架 .

http://blog.csdn.net/roger_ge/article/details/5531941 第一部分:前言 自动化测试或许是众多测试同行都在研究或准备研究的领域.结合自己的能力和公司的状况,选择合适的自动化工具.搭建正确而又高效的框架或许是个永远讨论不完的话题,正如应了那句话,没有最好,只有更好. 个人所在的公司当前开展的很多项目都是基于Win7和WPF开发的,之前想尝试用QTP对之进行录制和回放操作,不幸的是,需要额外的WPF插件支持:另外QTP的脚本语言是VBScript,虽

Jacob.UIAutomation.dll (.NET UI Automation封装) - 绝对原创

  UIAutomation是微软从Windows Vista开始推出的一套全新UI自动化测试技术, 简称UIA.在最新的Windows SDK中,UIA和MSAA等其它支持UI自动化技术的组件放在一起发布,叫做Windows Automation API. UIA定义了全新的.针对UI自动化的接口和模式. 分别是支持对UI元素进行遍历和条件化查询的TreeWalker/FindAll.定义了读写UI元素属性的UIA Property, 包括Name. ID.Type.ClassName.Loc

Fitnesse + Powerslim + UI Automation框架下抽取UI操作方法的思路

我们的自动化测试框架的Fitnesse + Powerslim,一般情况下会尽量避免在UI层面的操作,但是有些时候没有对应的命令行接口只能用UI去测试. Powershell里面作UI测试用得比较多的库是UI Automation,但是Powershell的语句相对来说比较繁琐,例如: Get-UIAWindow -ProcessName abc -Seconds 10 | Get-UIATab | Get-UIATabItem -Name "General"|Invoke-UIATa