微软UI自动化测试的技术演变(上)发布时间:2010-1-2816:07作者:熊力来源:www.cnblogs.com/stbchina字体:小中大|上一篇下一篇|打印|我要投稿|每周一问,答贴有奖Windows平台的桌面开发技术,从最原始的Win32SDK,发展到.NETWinForm,一直到今天的WPF和Silverlight,发生了翻天覆地的变化,相对应的UI自动化测试技术,也随之演变。微软UI自动化技术揭秘将分两个部分介绍Windows平台桌面程序的自动化技术。上篇将介绍从Win32SDK至今的UI自动化技术演变,下篇将着重介绍最新的UIAutomation(UIA)的内部实现和使用技巧。自动测试是指用一个程序自动地控制另外一个程序,模拟用户的操作进行测试。通常自动化测试涉及到下面三个步骤:测试源侦测测试源侦测是定位测试目标元素的过程。比如要测试Windows附件中的计算器,首先要把计算器窗口和其他程序比如写字板区分开。进一步测试计算器窗口菜单的时候,需要首先定位菜单条的位置,获取第二层子菜单等等。简单地说,自动化测试首先要能够获取从桌面开始的整个UI树结构,定位到特定测试目标。用户行为模拟用户行为模拟指模拟用户的输入,比如鼠标、键盘和触摸笔的操作,中间可能会涉及IME输入法、组合键、特定用户习惯,比如输入速度的模拟等。测试目标检查指获取测试元素的属性,比如读取窗口标题,Listbox的子元素,Checkbox的状态等等,以便进行测试检查。Win32SDK和WindowsMessage在.NET问世以前,Windows平台上的UI程序无外乎两种技术:Win32WindowsSDK或者DirectX。由于DirectX多用于专业领域如游戏和CAD,本文并不讨论。无论是MFC,VCL还是VB6,Win32SDK都是其根本,最终打交道的其实都是HWND和WindowsMessage。实现上述自动化的三个步骤无外乎三件法宝,Win32API,WindowsMessage和WindowsHook。测试程序首先通过FindWindowEx和EnumWindow遍历窗口和子窗口,找到测试元素比如某个按钮,然后可以通过WindowsMessage或者API检查测试目标。比如通过WM_GETTEXT或者GetWindowText读取窗口标题,通过GetWindowRect读取按钮坐标位置等等。对于用户行为模拟,可以直接通过SendKeyAPI来完成,当然也可以发送WM_CHAR或者WM_KEYDOWN通知等等。除此以外,WindowsHook更加丰富了技术的选取。通过WindowsHook,测试人员还可以直接监控、截取、模拟目标程序的Windows消息,实现更灵活的模拟,检查甚至录制的功能。WindowsSpy++(图一)虽然不是测试工具,也算是使用这套技术的典型例子。通过WindowsSpy++可以定位任意窗口,读取窗口属性,监视窗口消息等等。图一:MicrosoftSpy++采用Win32SDK和WindowsMessage的优点是直接,灵活。由于直接使用Win32API,没有额外的学习曲线,遇上问题可以直接参考Win32SDK解决。使用MessageHook使得测试程序可以灵活实现,直接对WindowMessage的操作不仅可以把很多情况化繁为简,还方便testhook的实现。(所谓testhook,是指产品中为了方便测试而专门设计的隐藏功能,该功能对普通用户不可见,只是为了方便测试。)缺点包括以下三个方面:使用复杂,实现成本高。Win32AP的使用上有很多需要特别注意的细节,比如有的Win32API不能跨进程工作,有的WindowsMessage只能发给当前线程所创建的窗口,稍有不慎,就导致测试程序不稳定。过于底层,不便使用。为了方便测试用例调用,需要对API进行封装,增加了实现成本。同时Win32API的也使得很多VB程序员不便调用。再者,不同的开发工具,比如MFC,VCL,以及后来的.NETFramework,在内部实现上对Win32API有很多细节的处理,要实现出针对各种情况都通用的测试框架,并非易事。比如,.NET中的WinFormControl对Win32HWND的维护是动态的,同一个WinFormControl的HWND在程序的生命周期内是可能发生改变的,这一点对于依赖HWND作为唯一标识的Win32API就是一个致命伤。无法操作自绘窗口。比如打开Excel的工作表,会发现表格中的每一个Cell并没有对应到HWND上。Excel的cell都是通过代码绘制,而不是依赖于现成的Win32Control。这就使得Win32API对于自绘窗口没有用武之地。MSAAMSAA的全称是MicrosoftActiveAccessibility。这是类似DCOM技术。技术模型是这样的,UI程序可以暴露出一个Interface,方便另一个程序对其进行控制。MSAA技术的初衷是为了方便残疾人使用Windows程序。比如盲人看不到窗口,但是盲人可以通过一个USB读屏器连接到电脑上,读屏器通过UI程序暴露出来的这个Interface,就可以获取程序信息,通过盲文或者其它形式传递给盲人。MSAA提供了如此方便的功能,UI自动化测试自然可以借用这项技术。MSAA暴露出来的Interface叫做IAccessible。测试程序和目标UI程序互操作流程如下:1.测试程序调用WindowsAPI:AccessibleObjectFromWindow,传入目标UI程序HWND。2.AccessibleObjectFromWindow函数向UI程序发送WM_GETOBJECT消息。3.UI程序创建实现了IAccessible的内部类,然后通过LresultFromObjectAPI把IAccessible接口返回给测试程序。4.测试程序拿到IAccessible接口,开始调用IAccessible接口函数操作测试目标。IAccessible接口里面的几个关键函数是:*IAccessible::get_accChild/IAccessible::get_accParent通过这两个函数,调用者可以浏览目标程序的窗口关系树,定位到UI元素。*IAccessible::accLocation/IAccessible::accHitTest读取和分辨目标元素的屏幕位置。*IAccessible::accName/IAccessible::accSelect读取元素的名字,对UI元素进行指定的操作,比如选取Listbox里面的某一项等等。*IAccessible::accValue开发人员可以自定义value属性的实现。比如针对折线图控件,开发人员可以在accValue中返回折线的坐标数列。MSAA的理念类似于testhook。通过主动让UI程序暴露一个接口来让调用者控制。在具体使用中,测试人员往往是结合MSAA和Win32API操作,取长补短。一方面对于UI元素丰富的属性,比如style,钩选状态,是否最大化和模拟用户输入等,继续采用Win32API。另一方面用MSAA的优势来弥补Win32API的一些不足,比如:由于MSAA有自己的get_accChild方法,使其控件树关系并不一定要和Win32HWNDd关系对应一致。对于自绘窗口,虽然说只有一个HWND,但是开发人员可以通过实现IAccessible接口来实现逻辑上的层次关系。比如Excel中就可以通过IAccessible把多个cell的子IAccessible接口暴露给调用者。IAccessible的实现是由开发者提供,开发者可以灵活地根据实际情况决定方法的实现。比如前面提到了折线图控件可以返回坐标数列。对于.NETWinForm,微软在Framework中就提供了IAccessible的默认实现,这样在具体实现中,就可以处理.NET动态维护HWND的细节等等针对MSAA的工具也有很多,比如AccExplorer(图二)可以像Spy++一样对指定程序进行控件的树形浏览,检查MSAA属性等。图二:AccExplorer如果您是开发人员,对于unmanagedUI程序的MSAA实现,参考MSDN中关于WM_GETOBJECT的说明返回IAccessibleinterface就可以了。对于managed程序,实现方法更简单,现成的例子可以参考:*Control..::.ControlAccessibleObjectClass*HowtocreateaccessiblecontrolsbyusingVisualBasic.NETorVisualBasic2005对于测试程序如何直接获取并使用IAccessible接口,并非本系列重点,所以并不提供更多介绍。在后面的文章中,会介绍如何隐含使用IAccessible和MSAA。MSAA也有自身的缺点:1.虽然说MSAA基于COM技术,但IAccessible并不是一个COM标准接口。比如使用者不需要调用CoInitialize即可使用,也无法通过QueryInterface进一步获取更多的自定义接口。这局限了MSAA所能提供的功能。2.IAccessible接口的定义有缺陷。里面不少方法是可有可无的,但是又缺少一些支持UI自动化的关键方法。比如它提供了accSelect支持控件的选取,但是却没有类似accExpand这样的方法支持树状控件的展开等。关于MSAA和UI自动化的更多渊源,MSAA设计理念,现状和缺陷,可以参考微软早期的一篇名为WhatisUIAutomation的文章。UIAutomation和WPFUIAutomation是微软从WindowsVista开始推出的一套全新UI自动化测试技术,简称UIA。在最新的WindowsSDK中,UIA和MSAA等其它支持UI自动化技术的组件放在一起发布,叫做WindowsAutomationAPI。和前面的介绍相比,我倾向于认为UIA是一项自动化测试“技术”,而MSAA和Win32API只是实现自动化测试的两种“方法”。这里区分“技术”和“方法”的原因是,一项“技术”往往有独立的模型,体贴的开发接口,用来专门解决某一类的问题,同时允许不同的实现细节。UIA可以被看作“技术”,是因为:UIA定义了全新的、针对UI自动化的接口和模式。分别是支持对UI元素进行遍历和条件化查询的TreeWalker/FindAll。定义了读写UI元素属性的UIAProperty,包括Name、ID、Type、ClassName、Location、Visibility等等。定义了UI元素行为的UIAPattern,比如Select、Expand、Resize、Check、Value等等。还引入了UIAEvent接口,可以让测试程序在某些事件发生后得到通知,比如新窗口打开事件等。以往的Win32和MSAA设计出发点并不是为解决UI自动化。Win32旨在提供的通用开发接口,MSAA旨在提供程序的多种访问方式。相反,UIA的设计目的,以及新引入的模式和接口都完全是针对UI自动化测试的。在后面的文章中我们会详细分析UIA的内部实现。可以看到,UIA这一套接口和模式,可以在不同平台,不同开发工具中实现和使用。其内部实现方式也因地制宜,前后的兼容性都照顾得很好。同时,UIA提供了托管的和非托管两种API,这些都是Win32和MSAA无法比拟的。下面一段简单的C#代码演示了如何使用UIA测试Windows自带计算器完成计算3+5-2的操作(下述代码可能需要修改以适应不同Windows版本的calc.exe程序。本代码使用VisualStudio2008针对Windows2008ServerR2English编写)。UIAutomation和WPFUIAutomation是微软从WindowsVista开始推出的一套全新UI自动化测试技术,简称UIA。在最新的WindowsSDK中,UIA和MSAA等其它支持UI自动化技术的组件放在一起发