1. 程式人生 > WINDOWS開發 >pywinauto之PC端windows自動化測試

pywinauto之PC端windows自動化測試

pywinauto是一個用純Python編寫的GUI自動化庫,併為Windows GUI精心開發。最簡單的是,它允許您將滑鼠和鍵盤操作傳送到Windows和Linux上的對話方塊和控制元件,而到目前為止,僅Windows才支援更復雜的基於文字的操作(正在開發Linux AT-SPI支援)。

pywinauto是一組用於自動化Microsoft Windows GUI的python模組。 最簡單的是,它允許您將滑鼠和鍵盤操作傳送到視窗對話方塊和控制元件。

pywinauto中文文件學習網址:https://www.kancloud.cn/gnefnuy/pywinauto_doc/1193035

一、環境安裝

首先保證電腦已經安裝好python、pip然後會直接通過模組命令安裝第三方庫pywinauto:pip3 install pywinauto

其次環境檢查命令列中開啟python直譯器,執行以下程式碼,windows自帶的記事本會被啟動,若無報錯,則證明pywinauto已安裝成功。

>>> from pywinauto.application import Application

>>> app = Application(backend="uia").start("notepad.exe")

技術分享圖片

如果對記事本做一些簡單的操作,比如說如下:

from pywinauto.application import Application

# 執行目標應用程式
app = Application(backend="win32").start("notepad.exe")
# 鍵入一個文字字串
app.UntitledNotepad.Edit.type_keys("開始輸入文字。。。",with_spaces=True)
# 選擇一個選單項
app.UntitledNotepad.menu_select("幫助->關於記事本")
# 單擊一個按鈕
app.關於記事本.確定.click()
# 關閉記事本
app["notepad.exe"].close()

技術分享圖片

注:因為我的是中文版本的記事本,所以程式碼裡也要對號入座。

二、PC端元素定位工具介紹及判斷backend

就是說在我們安裝好Pywinauto之後,首先要確定哪種可訪問性技術(pywinauto的backend)可以用於我們的應用程式。

在windows上受支援的輔助功能技術有兩種:

◆ Win32 API (backend="win32") 預設backend

◆ MS UI Automation (backend="uia")

如果您不能確定程式到底適用於那種backend,可以藉助於GUI物件檢查工具來做,常用的檢查工具有Inspect.ex,Spy++ 等。

1.Backend判斷
Pywinauto中backend有兩種:win32和uia,預設為win32。可使用spy++和Inspect工具判斷backend適合寫哪種。例如:如果使用Inspect的UIA模式,可見的控制元件和屬性更多的話,backend可選uia,反之,backend可選win32。

2.工具介紹

Spy++ (定位元素工具(win32))
Inspect(定位元素工具(uia))
UI Spy (定位元素工具)
Swapy(可簡單生成pywinauto程式碼)
三、啟動並建立一個例項物件

連線應用程式,首先需要用到pywinauto.application.Application()來建立一個應用程式物件,然後再連線到應用程式。

有如下兩種方法:

1.方式一:直接通過start方法開啟操作的應用程式
start()用於還沒有啟動軟體的情況。timeout為超時引數(可選),若軟體啟動所需的時間較長可選timeout,預設超時時間為5s。
start(self,cmd_line,timeout=app_start_timeout)
示例:
app = Application(backend = ‘uia’).start(r"E:\Office\Office14\EXCEL.exe)

2.連方式二:連線已經開啟應用程式,可以通過connect連線到指定的應用程式
connect()用於連線已經啟動的程式。連線一個已經執行的程式有以下幾種方法:
a)process:程序id
app = Application().connect(process=2341)
b)handle:應用程式的視窗控制代碼
app = Application().connect(handle=0x010f0c)
c)path:程序的執行路徑(GetModuleFileNameEx 模組會查詢程序的每一個路徑並與我們傳入的路徑去做比較)
app = Application().connect(path=“D:\Office14\EXCEL.exe”)

d)引數組合(傳遞給pywinauto.findwindows.find_elements()這個函式)
app = Application().connect(title_re=".*Notepad",class_name=“Notepad”)

注:應用程式必須先準備就緒,才能使用connect(),當應用程式start()後沒有超時和重連的機制。在pywinauto外再啟動應用程式,需要sleep,等程式start

四、 視窗、對話方塊及控制元件元素定位方式

開啟這個視窗之後,我們要操作該視窗的話,那麼就的先選中這個視窗,關於視窗的選擇有一下幾種方式:

技術分享圖片

技術分享圖片

1.window,dialog定位方式
1)基於title定位
a)如何獲取title?
title為視窗的名稱,可使用UISpy一類的定位元素工具去查詢。
如圖所示,該對話方塊中的title為Name屬性值:“替換”

技術分享圖片

b)若使用定位元素工具找不到title怎麼辦?
使用print_control_identifiers()方法打印出當前視窗或對話方塊中的所有title
格式:
app.YourDialog. print_control_identifiers()

c)使用title定位方式的寫法
Untitled_notepad = u’無標題 – 記事本’
app. Untitled_notepad.draw_outline(colour = ‘red’) #app.window(best_match=‘Untitled - Notepad’)
注:這種寫法適用於英文系統,英文軟體,其他語言的系統會存在編碼問題,需轉碼再使用。

app[‘無標題 – 記事本’] .draw_outline(colour = ‘red’)
注:適用於除英文外其他語言的系統,不用轉碼

2)top_window()定位
app.top_window() #此方法可返回應用軟體的最頂層視窗(是視窗,不是視窗彈出的對話方塊)
注:此方法目前沒有經過測試,它會返回應用程式的頂級視窗,但可能不是Z-Order中的頂級視窗。

3)關鍵字傳參
若以上方法不能滿足定位元素的需求,可使用以下列表中的引數傳參定位元素,引數可以組合使用。
示例:
app.window(class_name = ‘Notepad’).draw_outline(colour = ‘red’)

常用引數表:

可傳引數 對應屬性名稱備註
class_name ClassName
class_name_re 正則匹配window Classname
title Name Window視窗名
title_re 正則匹配視窗名
best_match 模糊匹配類似的title
handle 控制代碼
framework_id FrameworkId(一般情況下FrameworkId不是唯一的)
process ProcessId,程序id(注意:每次啟動後,程序id都會變)
control_id control_id
control_type ControlType()
auto_id AutomationId
2. control定位方式

基於title定位(同window,dialog中的title定位)
app[‘your dialog title’][‘your control title’]

app.dlg.control

層級定位
app.window(class_name = ’Notepad’).window(class_name = ‘#32770’)
app.window(class_name = ‘Notepad’).child_window(class_name = ‘#32770’)

wpath定位
若元素值為空,或不是唯一的情況下,可使用類似selenium中xpath的定位方式,根據查子元素的序號去定位元素。
示例:
app_window = app.window(class_name=‘Qt5QWindowIcon’) #定位登入視窗
app_window.children()[1].children()[0].children()[0] .children()[2] #定位使用者名稱輸入框控制元件(序號從0開始查)

五、常用方法

1**.除錯定位控制元件**

控制元件操作

程式視窗中的每一塊內容,都是一個控制元件,我們要對這個視窗的某一塊內容進行操作,就需要選擇到對應的控制元件。

關於控制元件選擇的方法有好幾種,最簡單的方法如下:

技術分享圖片

◆ 獲取所有控制元件

我們可以通過print_control_identifiers()這個方法,來獲取這個視窗下的直接子控制元件,如下:

技術分享圖片

技術分享圖片

a)print_control_identifiers(depth = None,filename = None)
以樹形結構打印出所有控制元件可識別出的標識
depth:列印的深度,預設時列印最大深度。
filename:將返回的標識存成檔案(生成的檔案與當前執行的指令碼在同一個路徑下)
eg:dlg. print_control_identifiers(filename =’a.txt’)

b)draw_outline(colour =’green’,thickness = 2,
fill = win32defines.BS_NULL,rect = None)
預設為在當前定位到的視窗或控制元件周圍畫出一條邊界線,方便我們看出定位到了哪個控制元件
colour:邊界線的顏色,預設為綠
thickness:線的粗細,預設為2
fill:以何種方式填充矩形(沒試過,詳見原始碼base_wrapper.py)
rect:根據座標畫出矩形(預設是在當前定位到的元素上畫出一個矩形)
c) is_dialog 判斷是否為dialog

2. 隱式等待
a) wait(wait_for,timeout = None,retry_interval = None)
wait_for可傳入五種引數,可以組合傳參,但要以空格隔開:
exists: 視窗變成有效的控制代碼
visible: 視窗可見,沒有隱藏
enabled: 視窗沒有disable
ready: visible + enable
active: active
timeout:設定超時時間,若在n秒內沒有等到視窗在wait_for中傳入的幾種狀態,則會丟擲TimeoutError。
retry_interval:超時後,間隔n秒再次重試。
Dlg.wait(“exists ready”,timeout = 5,retry_interval = 3)

b) wait_not(wait_for_not,timeout = None,retry_interval = None)
等待視窗不處於某種狀態時。引數與wait傳參一致。

3. 輸入框輸入

內容輸入的方法:type_key()

Dlg.control.type_keys(“xxxxx”)
4. 選單欄
menu_select()
eg:app.window.menu_select(Edit -> Replace)
5. 滑鼠點選
a)click() 點選Button控制元件
b)check_by_click() 通過click()方法勾選checkbox
c)uncheck_by_click() 通過click()方法取消勾選checkbox
d)get_check_state() 返回checkbox的勾選狀態(0沒勾選,1勾選,2不定)
e)is_checked(勾選返回true,為勾選返回false,不定返回None)
f)check() 勾選checkbox
g)uncheck() 不勾選checkbox
h)invoke() 點選(uia mode)
i)toggle () 勾選checkbox(uia mode)

pywinauto操作滑鼠的所有方法都封裝在pywinauto. mouse這個模組中,使用滑鼠之前。

首先要匯入mouse模組,mouse模組中包含了一系列的滑鼠操作事件。

◆ pywinauto. mouse

滑鼠移動:move方法

move(coords=(x軸座標,y軸座標))

緩慢移動滑鼠案例

技術分享圖片

滑鼠點選:click

技術分享圖片

6. 鍵盤操作
“+”:Shift
“^”:Control
“%”:Alt

通過鍵盤完成以下操作:全選(ctrl+A) 複製(Ctrl+C) 貼上(Ctrl+V) 回車(Enter) 貼上(Ctrl+V)

◆ pywinauto.keyboard.send_key

pywinauto模擬操作鍵盤,需要使用到 pywinauto.keyboard.send_keys這個方法:

技術分享圖片

◆ 常見的按鍵操作

##### 字母按鍵用按鍵小寫字母表示

常用的一些按鍵

技術分享圖片

按鍵修飾符

技術分享圖片

更多的鍵盤操作大家可以參考官網文件