說明:如下內容是根據2010年我在公司的一次關於UI Automation的Workshop上的PPT整理而來,在公司我和幾位同事基於UI Automation開發了一款很是強大的UI自動化測試工具,此工具已經在公司獲得普遍運用(有十幾個產品採用),用於替代昂貴的、且腳本很難維護的商用軟件。此文只探討UIA相關的一些通用技術和一點點UI自動化測試工具的設計經驗,由於保密的須要,涉及到公司的這款測試工具部分此文不作介紹。正則表達式
在沒有MSUIA(Microsoft UI Automation,如下簡稱UIA)以前,你們只能經過MSAA(Microsoft Active Accessibility)、Win32 API等Native的方式來操控Windows控件,要想本身寫一個UI自動化測試工具是很難很難的,所以這一領域一直被大廠商所壟斷,價格也貴得驚人,不是大的軟件公司也是用不起這些工具的(除非盜版),好比QTP、Robot、SilkTest等商用工具。UIA定義了一套全新的、針對UI自動化的接口和模式,以往的Win32和MSAA設計出發點並非爲解決UI自動化(Win32旨在提供的通用開發接口,MSAA技術的初衷則是爲了方便殘疾人使用Windows 程序),而UIA的設計目的(微軟也須要一套技術、工具來自動化測試本身的產品)、以及新引入的模式和接口都徹底是針對UI自動化測試的。UIA的出現,讓草根UI自動化測試工具成爲一種可能,看完本文你如有這樣的需求就趕忙本身造一個吧:)架構
在繼續介紹UIA以前,你們須要先熟悉UIA的幾個名詞術語。app
在UIA裏,每個UI控件便是一個Automation Element,全部的Elements是存儲在一個樹狀結構中的,Windows的桌面是這顆樹的根結點(RootElement)。ide
UIA tree就是上面所指的樹,每一個Application均可以看做是一棵子樹。工具
Element都有一些屬性(Properties),好比Automation ID、Name、ControlType等,要找到一個控件主要是經過這些的屬性來查找的。測試
在找到一個控件後,對一個控件進行操控的時候就須要用到這個控件支持的控制模式(Control patterns)了,好比:一個TextBox的ValuePattern能夠用來獲取TextBox裏面的文字。ui
當UI控件有什麼變更的時候,可能會觸發一些事件(好比:彈出HelpText),若是有Client訂閱了這個事件則會收到事件的通知。this
上圖左邊那部分叫Client,本文指的是UI自動化測試工具,右邊叫Application,指的是被測運用程序。Client和Application在啓動的時候都會載入UI Automation Core(UIAutomationCore.dll),UI自動化測試工具就是經過UI Automation Core來操控運用程序的。從這個架構圖上也能夠看到UIA封裝了一些MSAA和Win32的接口、屏蔽了Win32和.NET運用程序的差別,UI Automation Core對外提供了統一的接口,這也就大大簡化了Client這邊的實現。spa
基於UIA這套體系實現UI自動化須要解決的兩個核心的問題,一是控件查找(Find Controls);二是控件操做(Control manipulation),下面對此分別進行介紹。設計
UIA除了提供了最基本的遍歷整個UIA tree的API(TreeWalker)外,另外也提供了一些Build-in的控件查找API。
TreeWalker是標準的對UIA tree的遍歷API,它是一切控件查找API的基礎。
UIA自帶的這些Build-in的查找API是基於TreeScope和Filting Condition的,查找控件須要定義一個查找範圍和過濾條件。
下面是一個最簡單的示例,在RootElement桌面下查找子結點裏Name屬性是「Simple App」的一個控件,由於是在桌面的子結點(一級),它會是一個Application:
Condition winNameCond = new PropertyCondition(AutomationElement.NameProperty, "Simple App"); AutomationElement app = AutomationElement.RootElement.FindFirst(TreeScope.Children, winNameCond)
經過上面的Find Controls找到一個控件後,接下來就是如何操做它實現UI自動化的問題了,好比:點擊一個Button,選擇一個TreeViewItem等等。下面是一個已作好封裝的UITextBox這個控件類裏獲取TextBox的文字的參考實現:
public virtual string GetText() { object o = new object(); if (this.Element.TryGetCurrentPattern(ValuePattern.Pattern, out o)) { ValuePattern pattern = o as ValuePattern; return pattern.Current.Value; } else { return ""; } }
如上面的代碼所示,控件操做有一個固定的模式,首先嚐試獲取控件的Control Pattern,若是控件存在這樣的Control Pattern就經過這個Pattern來操控控件,若是沒有則須要自定義這個操做或拋出異常等。
直接基於UIA來實現UI自動化不是不能夠,但沒有人會這麼蠻幹。爲了獲取一個Textbox裏的文字這樣簡單的事情,獲得處拷貝上面那段的代碼,這是不可取的。因此針對上面說的兩個核心的問題,咱們須要在UIA上進行一些簡化、封裝(固然光有這兩點是不夠的,好比還須要提供一些Native的支持、UI同步、Log等功能,本文對此不作討論):
封裝經常使用控件的基本操做,如:Button的Click、TreeView的Expand和Collapse、Datagrid的操做等等,使控件的操做變成一個簡單的API調用,能夠考慮把UIA ControlType裏定義的30幾種控件中最經常使用的控件基本操做都實現了,這樣寫測試腳本的時候就很安逸了。一些產品中可能會使用一些非標的控件,對於這些自定義的控件,用標準控件的操控API可能無論用,一般經過下面兩種方式來解決這個問題,一是繼承標準控件,重寫操控API的實現,若是可以實現的話;二是讓開發人員改代碼,儘可能不要使用非標控件:)
當有了應手的測試工具後,測試腳本的維護依然是個老大難的問題,這個須要有一個好的自動化測試framework來隔離UI的變化,儘可能減小維護成本,一個好的framework大致須要有下面幾級的分層:
總之,經過UIA實現一套本身的強大的UI自動化測試工具不是不可能,但願本文對一些從事UI自動化測試的同窗有所幫助。
原文地址:http://feilong.me/2011/01/ms-ui-automation-tool-design-guide