m Technology I技术 微软UI自动化测试的 技术演变(上) ●文/熊力 Windows平台的桌面开发技术,从最原始的Win32 SDK,发展到.NET WinForm,一直到今天的WPF和 Silverlight,发生了翻天覆地的变化,相对应的u咱动化测试技术,也随之演变。 自 动拟化地用测控户试制的是另操指作外用~进一个行个测程程序试序,。模通自 win32 SDK ̄llWindows Message Microsoft Spy++(图1)虽然不 在.NET问世以前,Windows平台 是测试工具,也算是使用这套技术的 上的Ul程序无外乎两种技术:Win32 典型例子。通过Microsoft Spy++可以 常自动化测试涉及下面三个步骤。 SDK或者DirectX。由于DirectX多用 定位任意窗口,读取窗口属性,监视 于专业领域如游戏 ̄ICAD,本文并不 窗13消息等等。 测试源侦测 讨论。 测试源侦测是定位测试目标元素 无论是MFC、VCL还是VB6, 的过程。比如要测试Windows附件中 Wi n32 SDK都是其根本,最终打 的计算器,首先要把计算器窗13和其 交道的其实都是HWND和Windows 他程序比如写字板区分开。进一步测 Message。实现上述自动化的三个 试计算器窗口菜单的时候,需要首先 步骤无外乎三件法宝:Win32 API, 定位菜单条的位置,获取第二层子菜 Windows Message和Windows Hook。 单等等。简单地说,自动化测试首先 测试程序首先通过FindWin. 要能够获取从桌面开始的整个Ul树结 dowEx ̄13EnumWindow遍历窗口和子 构,定位到特定测试目标。 窗口,找到测试元素比如某个按钮, 图1 Microsoft Spy++ 然后可以通过Windows Message或 采用Win32 SDK和Wind0-WS 用户行为模拟 者API检查测试目标。比如通过WM Message的优点是直接,灵活。由于 用户行为模拟指模拟用户的输 GETTEXT或者GetWindowText读取 直接使用win32 API,没有额外的学习 入,比如鼠标、键盘和触摸笔的操 窗口标题,通过GetWindowRect读取 曲线,遇上问题可以直接参考Win32 作,中间可能会涉及IME输入法、组合 按钮坐标位置等等。对于用户行为模 SDK解决。使用Message Hook使得测 键、特定用户习惯,比如输入速度的 拟,可以直接通过SendKey API来完 试程序可以灵活实现,直接对Window 模拟等。 成,当然也可以发送WM CHAR或者 Message的操作不仅可以把很多情况 WM KEYDOWN通知等等。 化繁为简,还方便test hook的实现。 测试目标检查 除此以外,Windows Hook更加丰 (所谓test hook,是指产品中为了方 指获取测试元素的属性,比如 富了技术的选取。通过Windows Hook, 便测试而专门设计的隐藏功能,该功 读取窗口标题,Listbox的子元素, 测试人员还可以直接监控、截取、模拟 能对普通用户不可见,只是为了方便 Checkbox的状态等等,以便进行测试 目标程序的Windows ̄息,实现更灵活 测试。) 检杳。 的模拟,检查甚至录制的功能。 缺点包括以下3个方面。 100程序员 Enterprise l企业开发 使用复杂,实现成本高。Win32 API的使用上有很多需要特别注意的细 节,比如有的Win32 API不能跨进程工 作,有的Windows Message只能发给 当前线程所创建的窗口,稍有不慎, 就导致测试程序不稳定。 术。MSAA暴露出来的lnterface叫做 IAccessible。测试程序和目标Ui程序 互操作流程如下: 1.测试程序调用windOWS APl: AccessibleObjectFromWindow,传入目标 Ul程序HWND。 2.AccessibleObjectFromWindow函 数向UI程序发送WM GEToBJECT消息。 就可以通过lAccess.ble把多个Cell的子 IAccessible接口暴露给调用者。 IAccessible的实现是由开发者 提供,开发者可以灵活地根据实际情 况决定方法的实现。比如前面提到了 折线图控件可以返回坐标数列。对于 .过于底层,不便使用。为了方便 测试用例调用,需要对API进行封装, NET WinForm,微软在Framework中 3.uI程序创建实现了IAccessible的 内部类,然后通过LresultFromObject API  ̄lAccessible接口返回给测试程序。 4.测试程序拿到IAccessible接口,开 始调用IAccessible接口函数操作测试目标。 就提供了IAccessible的默认实现,这 增加了实现成本。同时Win32 API的 也使得很多VB程序员不便调用。再 者,不同的开发工具,比如MFC, VCL,以及后来的.NET Framework, 样在具体实现中,就可以处理.NET动 态维护HWND的细节等等。 针对MSAA的工具也有很多,比 如AccExpIorer(图2)可以像Spy++ 一IAccessible接口里面的几个关键 函数是: ●IAcceSSibIe1.getaccChiId/ —在内部实现上对Win32 API有很多细 样对指定程序进行控件的树形浏 节的处理,要实现出针对各种情况 都通用的测试框架,并非易事。比 如,.NET中的WlnForm COntroI对 Win32 HWND的维护是动态的,同一 个WinForm Control的HWND在程序 的生命周期内是可能发生改变的,这 一览,检查MSAA属性等。 IAccessible::get accParent通过这两个函 数,调用者可以浏览目标程序的窗13关系 树,定位 ̄rlUl元素。 ●IACcessibIe::accLocation/l Access_ble::accH_l1_est读取和分辨目标元 素的屏幕位置。 ●IA ccessjbIe::a ccN ame,J 点对于依赖HWND作为唯一标识的 Win32 API就是一个致命伤。 Accessible::accSelect读取元素的名字,对 无法操作自绘窗口。比如打开 Excel的工作表,会发现表格中的每一 个Cell并没有对应到HWND上。Excel的 Cell都是通过代码绘制,而不是依赖于 现成的Win32 Control。这就使得Win32 API对于自绘窗口没有用武之地。 Ul元素进行指定的操作,比如选取Listbox 里面的某一项等等。 ●IAccessible::accValue开发人员可 以白定义value属性的实现。比如针对折线 图控件,开发人员可以在accValue中返回 折线的坐标数列。 图2 AccExplo ̄r 如果您是开发人员,对于 MSAA的理念类似于test hook。 unmanaged UI程序的MSAA实现,参 考MSDN中关于WM GETOBJECT的 说明返回IAccessible interface就可以 通过主动让UI程序暴露一个接口来让 MSAA MSAA的全称是Microsoft Active Accessibility。它类似于DCOM技术。 调用者控制。在具体使用中,测试人 员往往是结合MSAA和Win32 APl操 作,取长补短。~方面对于Ul元素丰 富的属性,比如style、钩选状态、是 了。对于managed程序,实现方法更 简单,现成的例子可以参考: ●Contro1.o 们lAccessIbleo 争d Class ●How to create accessible controls by using Visual Basic NET or isualV Basic 2005 技术模型是这样的,UI程序可以暴露 出一个Interface,方便另一个程序对 否最大化和模拟用户输入等,继续采 用Win32 API。另一方面用MSAA的 其进行控制。MSAA技术的初衷是为 了方便残疾人使用Windows程序。 比如盲人看不到窗口,但是盲人可以 优势来弥补Win32 API的一些不足, 下面举例说明这~点。 对于测试程序如何直接获取并 使用IAccessible接13,并非本系列 重点,所以并不提供更多介绍。在后 面的文章中,会介绍如何隐含使用 IAccessible和MSAA。 通过一个USB读屏器连接到电脑上, 读屏器通过Ul程序暴露出来的这个 Interface,就可以获取程序信息,通 由于MSAA有自己的get_accChild 方法,使其控件树关系并不一定要和 Win32 HWND的关系对应一致。对于自 绘窗口,虽然说只有一个HWND,但是 开发人员可以通过实现IAccessible接口 来实现逻辑上的层次关系。klS ̄l:lExcel中 MSAA也有自身的缺点。 1.虽然说MSAA基于COM技术,但 IAccessible并不是一个COM标准接1:3。比如 过盲文或者其他形式传递给盲人。 MSAA提供了如此方便的功能, UI自动化测试自然可以借用这项技 使用者不需要调用ColnitializeEP可使用,也无 2O1O 01 101 m Technology I技术 法通过Querylnterface进一步获取更多的自定 义接口。这局限了MSAA所能提供的功能。 在提供的通用开发接口,MSAA旨在 提供程序的多种访问方式。相反,UIA 的设计目的,以及新引入的模式和接 口都完全是针对U咱动化测试的。 测试的第一步是通过UlA Condition 来找到计算器的按钮: Condition conditions=new 2.IAccessible接13的定义有缺陷。 里面不少方法是可有可无的,但是又缺少 一些支持Uf自动化的关键方法。比如它提 AndCondition(new PrOpertyCO ndition(AutomationE1ement. 供了accSelect支持控件的选取,但是却没 有类似accExpand这样的方法支持树状控 件的展开等。 在后面的文章中我们会详细分析 UIA的内部实现。可以看到,UIA这一 套接口和模式,可以在不同平台,不 同开发工具中实现和使用。其内部实 现方式也因地制宜,前后的兼容性都 照顾得很好。同时,UIA提供了托管的 和非托管两种API,这些都是Win32和 MSAA无法比拟的。 Automation工dProperty,“135” / 按钮5的AutomationID标识符 /),new PrePertyCondition(Automation Element.ControlTypeProperty, 关于MSAA和UI自动化的更多渊 源,MSAA设计理念,现状和缺陷, controlType.Button)) AUtomationE1ement btn=ca1cWindow. 可以参考微软早期的一篇名为“What is UI Automation”的文章。 FindAl1(TreeScoPe.Descendants conditions)[0] 测试的第二步是调用Button的 nvoke Pattern完成按钮点击: InvokePattern UIA和WPF UIAutomation是微软从Windows Vista开始推出的一套全新UI自动化测 下面一段简单的C撑代码演示了 如何使用UIA测试Windows自带计算 咄呲. ; 器完成计算3+5—2的操作(下述代码 可能需要修改以适应不同Windows版 本的calc.exe程序。本代码使用Visual StudjO 2008针对WindOWS 2008 invokeptn;(InvokePattern)btn. etCurrentPattern(InvokePattern. 试技术,简称UIA。在最新的Windows SDK中,UIA和MSAA等其他支持UI自 动化技术的组件放在一起发布,叫做 Windows Automation API。 Pattern) !invokeptn.Invoke() }测试的第三步是找到计算器输出 Server R2 English编写)。 首先是启动calc.exe进程,使 用WindOWOpenEvent捕获新打开 的窗口: Automation.AddAutomatio nEventHand1er fWindowPat tern.Wind0w0DenedEvent. AutomationElement.ReotE1ement 和前面的介绍相比,我倾向于认 为UIA是一项自动化测试“技术”, 框,并获取输出框的输入,进行测试 结果校验。 n d n t t C n x t n 谤守e 而MSAA和Win32 AP1只是实现自动化 测试的两种“方法”。这里区分“技 术”和“方法”的原因是,一项“技 术”往往有的模型,体贴的开发 接口,用来专门解决某一类的问题, 同时允许不同的实现细节。UIA可以被 一 一∞ = ∞∞,量詈_ 嘶m晰_。n : 瞄舌 ∞毗誉罐 l b ~三 。TreeScoDe.Chi1dren. eventHand1er); System.Dia口nostics.Process. 叩 ,=_。, 该 看作“技术”,是因为: UIA定义了全新的、针对Ul自 动化的接口和模式。分别是支持对 UI元素进行遍历和条件化查询的 TreeWalker/FindAll。定义了读写Ul元 Start(“calc.exe”) 在新窗口打开事件的相应函数 中,需要判断新打开的窗口是否为计 算器窗口,如果是,则开始测试。 凳 搀曼.蚍 .1 ~ 榆 触 素属性的UIA Prope ̄y,包括Name、 ID、Type、ClassName、Location、 UIA的优势 UIA的优势非常明显,主要包括 以下几点: 1.适应不同类型的Ul程序,包括 Win32、WinForm、WPF和Silverlight。 Visibility等等。定义了UI元素行为的 UIA Pattern,比如Select、Expand、 Resize、Check、Value等等。还引入 了UIA Event接口,可以让测试程序在 某些事件发生后得到通知,比如新窗 口打开事件等。 由于WPF和Silverlight中的子窗1:3和控件 并不是传统的HWND,所以Win32 API和 MSAA为力。而UIA可以直接支持这 两种程序。 2.兼容传统的Win32和MSAA模 以往的Win32和MSAA设计出发 点并不是为解决UI自动化。Win32旨 式。前面提到过,UIA技术的内部实现可 1O2程序员 Enterprise l企业开发 以多样化。这一点在下一篇文章中会详 细讨论。UlA通过一项叫做UIA<一>MSAA 的桥技术,针对传统程序,可以在内部实 现中借用MSAA的接口和直接调用Win32 API。这样不需要对控件或者程序的既有 实现做任何改动,就可以直接适用于UIA 的新模式。 3.新引入的T reeWaI ke r、UlA 动化技术和口动化框架 前面提到了UlA作为全新UI自动 化测试技术的优势,但这并不能解决 所有的Ul自动化问题。自动化框架正 是为了自动化技术没有完全解决的问 题。比如: 5.区分功能性测试和用户真实行为 模拟。前面提到,就点击按钮功能来说, 可以通过SendKey来模拟鼠标操作,或者 通过Windows Message来直接触发点击 事件。这两种不同方法各有优劣。比如当 按钮被其他元素遮挡,通过SendKey进行 模拟就会导致失败,而直接发送Windows Message ̄是会成功。孰优孰劣取决于要 达到的目的。如果单纯为了测试按钮点击 后导致的结果,通过Windows Message 1.自动化中的同步和等待。对于稍 复杂的UI程序,测试程序往往需要根据测 试目标的状态决定下一步的操作。比如测试 文件另存为功能的时候,若保存路径是网络 路径,可能会因为网络延迟导致整个UI停顿 比较长的时间。这个时候测试,程序如果不 Event、Pattern、Property模式易于使用, 贴合自动化测试。这些模式高度抽象了各种 UI自动化测试的需求,同时又不和传统模式 相冲突。比如执行点击按钮操作,传统方法 要么模拟鼠标键盘操作,要么发送Windows Message,而Message还分为WM 来模拟就省去了很多麻烦。相反,如果是 界面测试,通过SendKey来模拟就可以让 按钮被遮挡的bug暴露出来,而Windows Message则不能发现这样的问题。 COMMAND或者WM BUTTONDOWN。而 通过UIA Pattern,统一归类于Invoke接口, 这个接口对于测试者来说就统一了。无论是 Win32、WPF还是Silverlight按钮,都可以 顾当前状态而简单地执行下一步操作,比如 新建文件,很可能会因为Ul延迟而失败。正 确的做法是,测试程序应该等待文件保存成 功返回后,再进行下一步操作。这就是自 所以,单纯的某个自动化技术或 者方法也无法满足需求。为了解决上 述问题,各种自动化测试框架逐渐涌 现和发展。微软内部有多个不同的自 动化框架,设计理念和侧重点各有不 同。VisuaI Studio 2010将加入对自动 化测试的支持。在CodePlex上面,也 可以找到多种框架,比如White和Ul Automation Verify。 动化中同步和等待的一个例子。实现同步和 通过统一接口执行,从而把具体实现隔离 开。同时,调用者若希望继续沿用键盘鼠标 模拟,仍I19可以通过SendKey]]N上UIA获取 等待有多种方法,最简单粗暴的做法是硬编 码一个长时间的Sleep在测试代码中。稍微 好一点的做法可以采取小时问片的轮询状 坐标的方法实现。而UIA Event和对UI元素 支持条件化区域化搜索,更是极大简化了测 试人员的工作。 4.提供托管的和非托管接口,方便 各种工具的开发人员。同时提供了简洁方便 态检查,或者反复重试。借助UIA的Event Pattern,可以尝试捕获另存为窗口的关闭 WindowCIosedEvent。如果要做得完善一 点,可以把多种方法结合,另外再额外检查 目标程序的CPU使用情况,消息循环是否有 回应,设定超时时间等等。 2.冗繁的编码过程。对于一个UI 窗口,里面可能有几十个子控件或者子窗 口。在编写测试代码的时候,如果对这些 的方式支持UI程序和控件开发人员扩展,自 定义UIA的实现。比如通过AutomationPeer 来扩展基于WPF的控件,通过实现简单的 IRawElementProviderSimple来扩展基于 小结 本篇主要介绍和比较了Windows 平台Ul自动化技术的演变。UlA技术 势必成为Ul自动化的主流。在下一篇 中,我们会着重介绍UIA技术的内部机 制、原理、实现以及如何在程序和控 WinForm的控件等。具体细节在下一篇文章 子元素的获取,操作不能简化,势必导致 中会详细介绍。 5.针对WPF程序,除了支持基本的 端对端(End to End)UI自动化以外,还支 代码冗繁,难以维护。借助自动代码生成 和ORM(Obiecl Role Modeling1)等技术, 可以解决这个问题。比如可以用工具把窗 口及其子元素的关系和搜索条件都序列化 到XML文件中,然后采用ORM技术即可在 代码中轻松获取子元素。 3.多语言和本地化测试。多语言和本 地化的测试对Ul来说显得尤为重要。UI程序往 往通过资源文件来定义所显示的内容,这就要 件中扩展UIA的功能。@ 持基于AutomationPeer的单元测试。具体 例子可以参考UI Automation in Silverlight— Simulating User Interactions 6.提供了完善的工具、文档、开发 包、例子程序等。比如通过UI Spy(图3) 获取任意窗口或者元素的UIA信息。 琶瞄 ■——■●——●■■——●■■■—■■■一 求自动化测试要可以方便读取和定位程序的资 源文件,来支持多语言和本地化测试。 4.支持工具和辅助函数的匮乏。对于 大的项目研发,通过好的工具来减小开发成 本是非常必要的。就UI自动化来说,如果自 圈 熊事工S团e力业程服rv部师e,务r 微的,2器0软负与8中件责 开RW国测2发i研试中nd工发开活ow集具发动s 目录管理工具的WPF自动化测试。加入 产品开发团队前,服务于微软全球技术支 持中心,先后负责.NETf COM,ASPNET Visual Studio等产品的技术支持。著有 ((Windows用户态程序高效排错》。 -责任编辑:郭晓刚(guoxg@csdn.net) 2O1O O1 1O3 动化测试用例可以通过一次录制,多次播放 来做的话,成本会减少很多。在VS2010中 就提供了这样的录制.播放功能。详细视频 可以参考How to create record and playback Test Cases in Visual Studio Beta2。 图3 UI Spy