1. 程式人生 > 其它 >Windows UIA自動化測試框架學習--獲取qq好友列表

Windows UIA自動化測試框架學習--獲取qq好友列表

前段時間應公司要求開發一款針對現有WPF程式的自動化測試工具,在網上查資料找了一段時間,發現用來做自動化測試的框架還是比較多的,比如python的兩個模組pywinauto和uiautomation,但是pywinauto主要是封裝Win32的api,只侷限於winform框架,而python中的uiautomation其實是封裝的windows中的uia框架。基於專案效率考慮,所以最後決定使用windows中的UIAutomation框架。

這款WindowsUIA框架是同時支援wpf和winform,由於公司專案主要是wpf為主,所以以下學習和舉例也是基於wpf框架,沒有深入研究winform下的差異,但是大體上還是差不多的。

僅僅作為客戶端來invoke的話,只需要引用下面兩個dll即可,可以在.Net框架中查詢:UIAutomationClient.dll,UIAutomationTypes.dll

在UIA框架中,所有元素包括視窗和控制元件都表現為AutomationElement。一個程序中的UI在空間上分佈在一棵UI樹上面,只需要找到UI樹的根元素,就可以檢索到與之相關聯的其他任何元素

查詢視窗

查詢每個程序的根元素最常用的是根據控制元件控制代碼查詢,方法如下:


但是這個框架沒有提供檢索控制代碼的功能,所以需要和API配合使用:

 private static extern IntPtr findWindow(string lpClassName, string lpWindowName);

根據這個API獲取某個視窗的控制代碼,根據這個視窗的控制代碼獲取到AutomationElement,然後就可以通過下面的方法來查詢其他元素


以上兩個方法可以搜尋到這顆UI樹上的所有子控制元件,例如查詢某個Name屬性為MyButton的Button控制元件並觸發它的點選事件,就可以這樣實現:
   

PropertyCondition typeProperty = new PropertyCondition(AutomationElement.IsInvokePatternAvailableProperty, true);
                PropertyCondition nameProperty = new PropertyCondition(AutomationElement.AutomationIdProperty, “MyButton”);//搜尋條件
                AutomationElement ele = _mainAutomationElement.FindFirst(TreeScope.Subtree, new AndCondition(typeProperty, nameProperty));
                if (ele != null)
                {
                    if (ele.Current.IsEnabled)
                    {
                        InvokePattern pattern = (InvokePattern)ele.GetCurrentPattern(InvokePattern.Pattern);
                        pattern.Invoke();//觸發點選事件

                    } 

                 }

  

需要注意的是WPF中控制元件的屬性對映到AutomationElement有以下對應關係

Control property in WPF Property in AutomationElement
Name         AutomationIdProperty
Content   Name
Title   Name

視窗的Title和繼承ContentControl 的控制元件的Content  都會對映為AutomationElement中的Name屬性

通過上述方法,基本可以查詢到WPF中所有常用的控制元件,至於三方控制元件也有一定的相容性。

基於以上資訊,我們可以開發一個小工具,用於讀取QQ軟體的好友列表。

讀取QQ軟體的好友列表

這個小功能還是通過win32API+UIA框架實現的,獲取到qq好友列表中的成員備註名稱,圖中的好友姓名只取姓氏。


用到的API如下:

private const int MOUSEEVENTF_LEFTDOWN = 0x0002;//press the  mouse left button 
private const int MOUSEEVENTF_LEFTUP = 0x0004; //release the mouse right button
private const int MOUSEEVENTF_WHEEL = 0x800;//mouse wheel 
[DllImport("user32.dll", EntryPoint = "FindWindow")] 
private static extern IntPtr findWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
[DllImport("user32.dll", EntryPoint = "SetCursorPos")]
private static extern bool setCursorPos(int X, int Y);

第一個API是為了獲取qq視窗的控制代碼,第二個和第三個是用來模擬滑鼠操作。

主程式程式碼很簡單,基本流程是先檢索到列表名稱的控制元件,然後通過獲取座標控制滑鼠點選將列表展開,檢索該列表中所有的成員。檢索完成後將列表重新隱藏,避免列表成員太多,列表太長,影響下一個列表的展開。

            IntPtr ptr = findWindow(null,"QQ");
            List<string> tables = new List<string>() {"高中","小學","初中","網友","大學"};//好友列表名稱
            AutomationElement _mainElement = AutomationElement.FromHandle(ptr);
            foreach (var item in tables)
            {
                PropertyCondition type = new PropertyCondition(AutomationElement.IsControlElementProperty, true);
                PropertyCondition name = new PropertyCondition(AutomationElement.NameProperty, item);
                AutomationElement tableElement = _mainElement.FindFirst(TreeScope.Subtree, new AndCondition(type, name));
                if(tableElement!=null)
                {
                    Click(tableElement.GetClickablePoint().X, tableElement.GetClickablePoint().Y);//展開列表
                    AutomationElementCollection ac = _mainElement.FindAll(TreeScope.Subtree, new PropertyCondition(AutomationElement.IsSelectionItemPatternAvailableProperty, true));
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(tableElement.Current.Name+":");
                    Console.ForegroundColor = ConsoleColor.White;
                    foreach (AutomationElement ele in ac)
                    {
                        Console.WriteLine(ele.Current.Name.Substring(0, 1) + "**");
                    }
                    Click(tableElement.GetClickablePoint().X, tableElement.GetClickablePoint().Y);//重新隱藏列表
                }

            }

            Console.ReadLine();

  

通過控制滑鼠的API和UIA框架基本可以實現模擬任何人為操作,對實現windows app自動化測試是一個不錯的選擇