UIAutomation和WPFide
UIAutomation是微軟從Windows Vista開始推出的一套全新UI自動化測試技術, 簡稱UIA。在最新的Windows SDK中,UIA和MSAA等其它支持UI自動化技術的組件放在一塊兒發佈,叫作Windows Automation API。函數
和前面的介紹相比,我傾向於認爲UIA是一項自動化測試「技術」,而MSAA和Win32 API只是實現自動化測試的兩種「方法」。這裏區分「技術」和 「方法」的緣由是, 一項「技術」每每有獨立的模型,體貼的開發接口,用來專門解決某一類的問題,同時容許不一樣的實現細節。UIA能夠被看做「技術」,是由於:工具
UIA定義了全新的、針對UI自動化的接口和模式。 分別是支持對UI元素進行遍歷和條件化查詢的TreeWalker/FindAll。定義了讀寫UI元素屬性的UIA Property, 包括Name、 ID、Type、ClassName、Location、 Visibility等等。定義了UI元素行爲的UIA Pattern, 好比Select、Expand、Resize、 Check、Value等等。 還引入了UIA Event接口,可讓測試程序在某些事件發生後獲得通知,好比新窗口打開事件等。 開發工具
以往的Win32和MSAA 設計出發點並非爲解決UI自動化。Win32旨在提供的通用開發接口, MSAA旨在提供程序的多種訪問方式。相反,UIA的設計目的,以及新引入的模式和接口都徹底是針對UI自動化測試的。測試
在後面的文章中咱們會詳細分析UIA的內部實現。能夠看到,UIA這一套接口和模式,能夠在不一樣平臺,不一樣開發工具中實現和使用。其內部實現方式也因地制宜, 先後的兼容性都照顧得很好。 同時,UIA提供了託管的和非託管兩種API,這些都是Win32和MSAA沒法比擬的。spa
UIAutomtion中主要用AutomationElement 類來 表示 UI 自動化目錄樹中的一個 UI 自動化元素,幷包含由 UI 自動化客戶端應用程序用做標識符的值。設計
在reference中添加UIAutomationClient,UIAutomationTypes,UIAutomationProvider 和UIAutomationClientsideProviders。code
(Donet 3.0以上的項目中才有)blog
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Automation; using System.Windows; namespace ConsoleApplication2 { class Cal { AutomationElement calcWindow = null; string resultTextAutoId = "150"; string btn5AutoId = "135"; string btn3 = "133"; string btn2 = "132"; string btnPlus = "93"; string btnSub = "94"; string btnEqual = "121"; static void Main(string[] args) { Cal autoClient = new Cal(); //建立新窗口打開事件的回調,只有等計算器窗口打開後,測試開始執行 AutomationEventHandler eventHandler = new AutomationEventHandler(autoClient.OnWindowOpenOrClose); //把事件掛接在桌面根元素,開始監聽 Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, eventHandler); //啓動計算器程序,當計算器窗口打開後,新窗口事件獲得觸發 System.Diagnostics.Process.Start("calc.exe"); Console.ReadLine(); } void OnWindowOpenOrClose(object src, AutomationEventArgs e) { if (e.EventId != WindowPattern.WindowOpenedEvent) { return; } AutomationElement sourceElement; try { sourceElement = src as AutomationElement; //監察印發新窗口打開事件的窗口是不是計算器 //在正式代碼中,爲了支持本地化測試,字符串應該從資源文件中讀取 if (sourceElement.Current.Name == "計算器") { calcWindow = sourceElement; } } catch (ElementNotAvailableException) { return; } //開始執行測試 ExecuteTest(); } private void ExecuteTest() { //執行3+5-2 //調用函數執行按鈕點擊 ExecuteButtonInvoke(btn3); ExecuteButtonInvoke(btnPlus); ExecuteButtonInvoke(btn5AutoId); ExecuteButtonInvoke(btnSub); ExecuteButtonInvoke(btn2); ExecuteButtonInvoke(btnEqual); //調用getcurrentresult函數,獲取計算器輸出窗口的值 if (GetCurrentResult() == "6") { Console.WriteLine("execute pass!"); return; } Console.WriteLine("execute faile"); } //調用函數執行按鈕點擊 private void ExecuteButtonInvoke(string automationId) { //建立捕獲按鈕條件。該條件中有兩個判斷 //分別判斷automationid是否爲指定字符串 //以及控件類型是否爲按鈕 System.Windows.Automation.Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.AutomationIdProperty,automationId), new PropertyCondition(AutomationElement.ControlTypeProperty,ControlType.Button)); AutomationElement btn = calcWindow.FindFirst(TreeScope.Descendants,conditions); //獲取按鈕的invokepattern接口 InvokePattern invokeptn = (InvokePattern)btn.GetCurrentPattern(InvokePattern.Pattern); //調用invoke接口,完成按鈕點擊 invokeptn.Invoke(); } private string GetCurrentResult() { System.Windows.Automation.Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.AutomationIdProperty,resultTextAutoId), new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Text)); AutomationElement btn = calcWindow.FindFirst(TreeScope.Descendants, conditions); //得去text控件的名字,更名字就是輸出字符串 return btn.Current.Name; } } }