Python下編寫Windows自動化測試軟件


https://www.jianshu.com/p/be3c46c7a905

uiautomation模塊學習筆記


前段時間,由於個人需要,在網上查找了一些關於Windows平台下自動化測試的資料,最后找到了一款相當不錯的Python模塊:uiautomation,直接pip install uiautomation即可方便地獲取這個模塊。在學習這個模塊的同時,記些筆記,方便自己以后查閱,也方便大家翻閱。

0x00 概述

這個庫在Github上是開源的,地址:https://github.com/yinkaisheng/Python-UIAutomation-for-Windows
而且作者是一名中國人,還是南京人,讓我感覺十分親切。
這個庫可以說是十分貼合實際,在Windows平台下,絕大部分軟件都要遵循Windows的規范,也就是說窗口啊,句柄啊、控件啊這些東西,都是通用的,Windows向外提供了這些接口。先感謝一下yinkaisheng,他的工作就是進一步給這些接口做了整合,給Python的開發者提供了接口。這極大地方便了想要用Python開發自動化測試程序的人。

0x01 作者的readme文檔

  • 這個模塊是基於Windows的UIA技術實現的,系統最低需要WindowsXP SP3,支持MFC、WinForm、WPF、Metro UI(從Windows8開始Windows系統開發的一種新的窗口)、Qt和火狐,也就是說基於.Net技術的所有Windows窗體程序都支持,而其他的軟件,比如基於DirectUI開發的,這個模塊可能難以獲取到其中的信息。
  • 作者將這個模塊開源了,基於Apache2.0,這以為着源代碼可以任意復制,修改,使用以及再發布,贊!
  • 安裝方法很簡單,在已有Python和pypi環境的電腦上運行pip install uiautomation即可安裝,並且主程序automation.py也會自動復制到Python的Scripts文件夾下。
  • 同時作者也提供了C++ dll的源碼,但是在這里就不去涉及了。可以看出作者是名十分敬業的開發人員!
  • 可以簡單運行一下automation.py,直接運行的效果就是3秒后遍歷當前活動窗口的所有控件。對QQ運行的效果:


     
     

     
     

    可見效果十分明顯,窗口內的控件信息全部都顯示出來了,包括控件類型,控件的名稱,控件的位置(以像素為單位),句柄,控件樹深度等。同時,所有信息會保存到當前目錄下的@AutomationLog.txt文件中,方便查閱。

  • 作者提供了一個Demo,用於控制記事本程序:
import subprocess import uiautomation as automation print(automation.GetRootControl()) subprocess.Popen('notepad.exe') notepadWindow = automation.WindowControl(searchDepth = 1, ClassName = 'Notepad') print(notepadWindow.Name) notepadWindow.SetTopmost(True) edit = notepadWindow.EditControl() edit.SetValue('Hello') edit.SendKeys('{Ctrl}{End}{Enter}World') 

GetRootControl()方法將返回根控件,也就是整個Windows可視化的桌面(這么理解沒錯吧)
WindowControl(searchDepth=1,ClassName='Notepad')方法將創建一個WindowsControl對象,參數的作用是細化如何找到我們想要的控件,可用的參數有searchFromControl=None,searchDepth=0xFFFFFFF,searchWaitTime=SEARCH_INTERVAL,foundIndex=1,Name,SubName,ClassName,Depth等,可以去源碼下的Control類的初始化方法init看一下這些參數怎么用。

  • 接下來作者介紹了一個小工具Inspect.exe,這個工具是微軟提供的,可以用來探測UI的內容,這個程序自動集成在微軟的Windows SDK中,我電腦上正好安裝了Visual Studio和Windows SDK,應該可以找到這個程序。果然在工具集中找到了這個程序:


     
     

     
     

    可以看到使用效果非常好,窗口的構造一目了然!

  • 最后作者放了一些自己使用該模塊的截圖,可以看到,功能十分強大:


     

     

     

     

     

0x02 簡單了解實現原理

作者在readme文檔中外鏈了一篇博文,簡單介紹了實現原理,為了能更好地掌握這個庫的使用,這篇原理我也簡單的學習一下。(原文鏈接

在最早的Windows開發中是沒有自動化測試的概念的。1997年微軟在操作系統中集成了MASS(Microsoft Active Accessibility)組件,但是微軟開發MASS組件的初衷並不是為了自動化測試,而是提供了一套接口,讓開發者們可以方便的開發殘疾人士輔助軟件,比如讀屏軟件等。伴隨着自動化測試的應用越來越廣泛,微軟正視了自動化測試的需求,在MASS的基礎上,對其重新封裝設計並實現了UIAutomation的類庫(.NET)。從Win7系統開始的后續Windows操作系統都整合了Windows Automation API的所有功能。作者在閱讀了MSDN上的《UI Automation Client Programmer's Guide》和CodeMagazine上的《Creating UI Automation Client Applications》兩篇文章后,用Python和C++對UIAutomation做了一層簡單的封裝,方便了想要用Python開發自動化測試應用而對.Net平台又不太熟悉的人,比如我。

0x03 API學習摘要

之前也已經提到,這個模塊是作者對UIA用C++和Python簡單的做了一層封裝,只要能理解面向對象編程,學習難度也不是很大。正好,我在作者的CSDN博客里面找到了作者使用此模塊的實例(原文鏈接),就以此為學習的入口,代碼如下:

#!python3 # -*- coding: utf-8 -*- """ 本腳本可以獲取QQ2017(v8.9.4)群所有成員詳細資料,請根據提示做對應的操作 作者:yinkaisheng@foxmail.com """ import time import uiautomation as automation def GetPersonDetail(): detailWindow = automation.WindowControl(searchDepth= 1, ClassName = 'TXGuiFoundation', SubName = '的資料') details = '' for control, depth in automation.WalkControl(detailWindow): if isinstance(control, automation.EditControl): details += control.Name + control.CurrentValue() + '\n' details += '\n' * 2 detailWindow.Click(-10, 10) return details def main(): automation.Logger.WriteLine('請把鼠標放在QQ群聊天窗口中的一個成員上面,3秒后獲取\n') time.sleep(3) listItem = automation.ControlFromCursor() if listItem.ControlType != automation.ControlType.ListItemControl: automation.Logger.WriteLine('沒有放在群成員上面,程序退出!') return consoleWindow = automation.GetConsoleWindow() if consoleWindow: consoleWindow.SetActive() qqWindow = listItem.GetTopWindow() list = listItem.GetParentControl() allListItems = list.GetChildren() for listItem in allListItems: automation.Logger.WriteLine(listItem.Name) answer = input('是否獲取詳細信息?按y和Enter繼續\n') if answer.lower() == 'y': automation.Logger.WriteLine('\n3秒后開始獲取QQ群成員詳細資料,您可以一直按住F10鍵暫停腳本') time.sleep(3) qqWindow.SetActive() #確保群里第一個成員可見在最上面 left, top, right, bottom = list.BoundingRectangle while allListItems[0].BoundingRectangle[1] < top: automation.Win32API.MouseClick(right - 5, top + 20) for listItem in allListItems: if listItem.ControlType == automation.ControlType.ListItemControl: if automation.Win32API.IsKeyPressed(automation.Keys.VK_F10): if consoleWindow: consoleWindow.SetActive() input('\n您暫停了腳本,按Enter繼續\n') qqWindow.SetActive() listItem.RightClick() menu = automation.MenuControl(searchDepth= 1, ClassName = 'TXGuiFoundation') menuItems = menu.GetChildren() for menuItem in menuItems: if menuItem.Name == '查看資料': menuItem.Click() break automation.Logger.WriteLine(listItem.Name, automation.ConsoleColor.Green) automation.Logger.WriteLine(GetPersonDetail()) listItem.Click() automation.SendKeys('{Down}') if __name__ == '__main__': main() input('press Enter to exit') 

我用的環境是Pycharm2017.2社區版和Python3.6,這個模塊的內容主要集中在uiautomation.py文件中,學習方法就是去這個文件里看相關的代碼。先簡單看一下這個代碼,看看里面有哪些看不懂的,看不懂的地方就是要學習的地方。

首先是automation.WindowControl,這看起來是個對象,但是還不知道這個對象有哪些方法和屬性,下面的WalkControl和EditControl應該也是對象,從命名上看可能直接代表了窗體中的不同控件。control.CurrentValue應該是屬性,下面的detailWindow.Click()應該是模擬鼠標點擊的方法。再看main()函數,Logger.WriteLine()方法應該是跟日志有關,ControlFromCursor()可能是從鼠標獲取控件的方法......

這樣看一遍大概就知道應該去源碼里面找哪些定義了,我們利用PyCharm的跳轉定義功能可以很容易地找到定義這些類和方法的代碼,都在uiautomation.py這個文件中。源碼就不貼了,通過跳轉功能可以很容易地理解其中的方法與類之間的邏輯關系。這個文件中主要定義了“控件”這個類,就是兩千多行處的Class Control(.............):這一大段代碼,里面包含了所有對控件的方法和基本的屬性。方法有獲取控件名稱啊,內容啊等,屬性有位置啊,是否Active啊這些。然后由Control類派生出各個子類,代表具體的各種控件,比如WindowControl類表示窗口,EditControl類表示輸入框,ButtonControl類代表按鈕等等,幾乎涵蓋所有Win窗體程序的所有控件。並且作者在很多類下面做了詳細的注釋,閱讀起來應該沒有什么困難。理解的難點應該是這里面有大量關於WinForm開發的知識,需要一點基礎。

那么當我們將這些方法與類的定義搞清楚之后,我們就能讀懂這個實例的功能了。通過組合運用各個空間的屬性和方法,實現從QQ群窗口中獲得QQ群的信息。包括群號、群成員信息、聊天記錄等信息,並保存到文本文件。

0x04 后記

  • 果然多看,多寫才是提升實力的根本途徑,教材看一百遍不如自己摸索一遍!
  • Life is short,use Python!


作者:8f7aac77586a
鏈接:https://www.jianshu.com/p/be3c46c7a905
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM