GUI Python + pywinauto: c MS UI Automation |
Python pywinauto open source GUI Windows. :
"win32"
"uia"
). -., open source ( ).
SQA Days 20 ( ), Getting Started Guide pywinauto.
. GUI , , Selenium. :
, .
[+] -, .
[+] "record-replay" .
[-] , , , ..
[-] , .
[-] , .
(-): autopy, PyAutoGUI, PyUserInput . , ( -).
, . , ( /, ) , / ( ).
: ( -, - ).
[+] -
[+-] (, ), .
[-+] , .. CPU .
[-] (OCR), , => . , OCR , (welcome , ).
: Sikuli, Lackey (Sikuli-, Python), PyAutoGUI.
[+] , .. , , .
[+] => .
[+] , , .. CPU.
[-] - : open-source - accessibility . Windows/Linux/MacOS , TestComplete, UFT Squish.
[-] . , VirtualBox' . - accessibility . .
: TestStack.White C#, Winium.Desktop C# (Selenium ), MS WinAppDriver C# (Appium ), pywinauto, pyatom ( LDTP), Python-UIAutomation-for-Windows, RAutomation Ruby, LDTP (Linux Desktop Testing Project) Windows Cobra.
LDTP , - open-source ( ) accessibility . . , . , .
- testability. , TCP , : , .. , .
Windows , WPF Windows Store, Win32 API. , MFC, WTL, C++ Builder, Delphi, VB6 Win32 API. Windows Forms Win32 API .
: AutoIt ( VB) Python pyautoit, AutoHotkey ( , IDispatch COM ), pywinauto (Python), RAutomation (Ruby), win32-autogui (Ruby).
: MS UI Automation GUI Windows . : , Win32 API. .
custom COM ( , UIAutomationCore.dll), .NET namespace System.Windows.Automation
. , , , - UI . UIAutomationCore.dll ( UiaComWrapper C#, ).
COM :
(1) IUknown "the root of all evil". , user-friendly.
(2) IDispatch (, Excel.Application
), Python win32com.client ( pyWin32). .
(3) Custom , Python comtypes.
: TestStack.White C#, pywinauto 0.6.0+, Winium.Desktop C#, Python-UIAutomation-for-Windows ( UIAutomationCore.dll ), RAutomation Ruby.
, Linux X Window System ( Fedora 25 "" Wayland), "" /. , AT-SPI. AT-SPI registry , GUI ( Qt GTK).
: pyatspi2.
pyatspi2, , PyGObject. libatspi.so
. Reference Manual. pywinauto AT-SPI : libatspi.so ctypes. , GTK+ Qt . pywinauto 0.7.0 Linux 2018-.
MacOS AppleScript. - Python, , ObjectiveC. , , MacOS 10.6 pyobjc. pywinauto.
: Apple Script, ATOMac, pyatom. LDTP, . iTunes macOs, . : ( waitFor*
). , , .
GUI (, Spy tool). : , . :
C:\Program Files (x86)\Windows Kits\\bin\x64
. UI Automation MS AA (Active Accessibility, UI Automation)., , . Application.
--force-renderer-accessibility
, Inspect.exe). , Selenium . ( - ). . Application . subprocess.Popen
, , . , , .
from pywinauto.application import Application
app = Application(backend="uia").start('notepad.exe')
# , Notepad.exe
dlg_spec = app.UntitledNotepad
#
actionable_dlg = dlg_spec.wait('visible')
, Desktop
. , Win10 ( calc.exe
). Desktop
.
from subprocess import Popen
from pywinauto import Desktop
Popen('calc.exe', shell=True)
dlg = Desktop(backend="uia").Calculator
dlg.wait('visible')
(Application
Desktop
) , . "->", .
, pywinauto. / , . ( WindowSpecification) , .
:
>>> dlg_spec = app.window(title='Untitled - Notepad')
>>> dlg_spec
>>> dlg_spec.wrapper_object()
.wrapper_object()
. "" / ElementNotFoundError
( ElementAmbiguousError
, , ). "" - .
Python .wrapper_object()
, . . :
dlg_spec.wrapper_object().minimize() # debugging
dlg_spec.minimize() # production
. :
#
app.window(title_re='.* - Notepad$').window(class_name='Edit')
# ( AND)
dlg = Desktop(backend="uia").Calculator
dlg.window(auto_id='num8Button', control_type='Button')
pywinauto.findwindows.find_elements(...).
Python ( __getattribute__
). , , ( , ). , pywinauto "best match" , .
app.UntitledNotepad
# ,
app.window(best_match='UntitledNotepad')
- Unicode (, ), .., ( ):
app['Untitled - Notepad']
# ,
app.window(best_match='Untitled - Notepad')
? , . , , .
app.Properties.OK.click()
app.Properties.OKButton.click()
app.Properties.Button3.click()
( Button0
Button1
, Button2
, )app.OpenDialog.FileNameEdit.set_text("")
( )app.Properties.TabControlSharing.select("General")
- , . , , print_control_identifiers(). , . . . :
app.Properties.child_window(title="Contains:", auto_id="13087", control_type="Edit")
>>> app.Properties.print_control_identifiers()
Control Identifiers:
Dialog - 'Windows NT Properties' (L688, T518, R1065, B1006)
[u'Windows NT PropertiesDialog', u'Dialog', u'Windows NT Properties']
child_window(title="Windows NT Properties", control_type="Window")
|
| Image - '' (L717, T589, R749, B622)
| [u'', u'0', u'Image1', u'Image0', 'Image', u'1']
| child_window(auto_id="13057", control_type="Image")
|
| Image - '' (L717, T630, R1035, B632)
| ['Image2', u'2']
| child_window(auto_id="13095", control_type="Image")
|
| Edit - 'Folder name:' (L790, T596, R1036, B619)
| [u'3', 'Edit', u'Edit1', u'Edit0']
| child_window(title="Folder name:", auto_id="13156", control_type="Edit")
|
| Static - 'Type:' (L717, T643, R780, B658)
| [u'Type:Static', u'Static', u'Static1', u'Static0', u'Type:']
| child_window(title="Type:", auto_id="13080", control_type="Text")
|
| Edit - 'Type:' (L790, T643, R1036, B666)
| [u'4', 'Edit2', u'Type:Edit']
| child_window(title="Type:", auto_id="13059", control_type="Edit")
|
| Static - 'Location:' (L717, T669, R780, B684)
| [u'Location:Static', u'Location:', u'Static2']
| child_window(title="Location:", auto_id="13089", control_type="Text")
|
| Edit - 'Location:' (L790, T669, R1036, B692)
| ['Edit3', u'Location:Edit', u'5']
| child_window(title="Location:", auto_id="13065", control_type="Edit")
|
| Static - 'Size:' (L717, T695, R780, B710)
| [u'Size:Static', u'Size:', u'Static3']
| child_window(title="Size:", auto_id="13081", control_type="Text")
|
| Edit - 'Size:' (L790, T695, R1036, B718)
| ['Edit4', u'6', u'Size:Edit']
| child_window(title="Size:", auto_id="13064", control_type="Edit")
|
| Static - 'Size on disk:' (L717, T721, R780, B736)
| [u'Size on disk:', u'Size on disk:Static', u'Static4']
| child_window(title="Size on disk:", auto_id="13107", control_type="Text")
|
| Edit - 'Size on disk:' (L790, T721, R1036, B744)
| ['Edit5', u'7', u'Size on disk:Edit']
| child_window(title="Size on disk:", auto_id="13106", control_type="Edit")
|
| Static - 'Contains:' (L717, T747, R780, B762)
| [u'Contains:1', u'Contains:0', u'Contains:Static', u'Static5', u'Contains:']
| child_window(title="Contains:", auto_id="13088", control_type="Text")
|
| Edit - 'Contains:' (L790, T747, R1036, B770)
| [u'8', 'Edit6', u'Contains:Edit']
| child_window(title="Contains:", auto_id="13087", control_type="Edit")
|
| Image - 'Contains:' (L717, T773, R1035, B775)
| [u'Contains:Image', 'Image3', u'Contains:2']
| child_window(title="Contains:", auto_id="13096", control_type="Image")
|
| Static - 'Created:' (L717, T786, R780, B801)
| [u'Created:', u'Created:Static', u'Static6', u'Created:1', u'Created:0']
| child_window(title="Created:", auto_id="13092", control_type="Text")
|
| Edit - 'Created:' (L790, T786, R1036, B809)
| [u'Created:Edit', 'Edit7', u'9']
| child_window(title="Created:", auto_id="13072", control_type="Edit")
|
| Image - 'Created:' (L717, T812, R1035, B814)
| [u'Created:Image', 'Image4', u'Created:2']
| child_window(title="Created:", auto_id="13097", control_type="Image")
|
| Static - 'Attributes:' (L717, T825, R780, B840)
| [u'Attributes:Static', u'Static7', u'Attributes:']
| child_window(title="Attributes:", auto_id="13091", control_type="Text")
|
| CheckBox - 'Read-only (Only applies to files in folder)' (L790, T825, R1035, B841)
| [u'CheckBox0', u'CheckBox1', 'CheckBox', u'Read-only (Only applies to files in folder)CheckBox', u'Read-only (Only applies to files in folder)']
| child_window(title="Read-only (Only applies to files in folder)", auto_id="13075", control_type="CheckBox")
|
| CheckBox - 'Hidden' (L790, T848, R865, B864)
| ['CheckBox2', u'HiddenCheckBox', u'Hidden']
| child_window(title="Hidden", auto_id="13076", control_type="CheckBox")
|
| Button - 'Advanced...' (L930, T845, R1035, B868)
| [u'Advanced...', u'Advanced...Button', 'Button', u'Button1', u'Button0']
| child_window(title="Advanced...", auto_id="13154", control_type="Button")
|
| Button - 'OK' (L814, T968, R889, B991)
| ['Button2', u'OK', u'OKButton']
| child_window(title="OK", auto_id="1", control_type="Button")
|
| Button - 'Cancel' (L895, T968, R970, B991)
| ['Button3', u'CancelButton', u'Cancel']
| child_window(title="Cancel", auto_id="2", control_type="Button")
|
| Button - 'Apply' (L976, T968, R1051, B991)
| ['Button4', u'ApplyButton', u'Apply']
| child_window(title="Apply", auto_id="12321", control_type="Button")
|
| TabControl - '' (L702, T556, R1051, B962)
| [u'10', u'TabControlSharing', u'TabControlPrevious Versions', u'TabControlSecurity', u'TabControl', u'TabControlCustomize']
| child_window(auto_id="12320", control_type="Tab")
| |
| | TabItem - 'General' (L704, T558, R753, B576)
| | [u'GeneralTabItem', 'TabItem', u'General', u'TabItem0', u'TabItem1']
| | child_window(title="General", control_type="TabItem")
| |
| | TabItem - 'Sharing' (L753, T558, R801, B576)
| | [u'Sharing', u'SharingTabItem', 'TabItem2']
| | child_window(title="Sharing", control_type="TabItem")
| |
| | TabItem - 'Security' (L801, T558, R851, B576)
| | [u'Security', 'TabItem3', u'SecurityTabItem']
| | child_window(title="Security", control_type="TabItem")
| |
| | TabItem - 'Previous Versions' (L851, T558, R947, B576)
| | [u'Previous VersionsTabItem', u'Previous Versions', 'TabItem4']
| | child_window(title="Previous Versions", control_type="TabItem")
| |
| | TabItem - 'Customize' (L947, T558, R1007, B576)
| | [u'CustomizeTabItem', 'TabItem5', u'Customize']
| | child_window(title="Customize", control_type="TabItem")
|
| TitleBar - 'None' (L712, T521, R1057, B549)
| ['TitleBar', u'11']
| |
| | Menu - 'System' (L696, T526, R718, B548)
| | [u'System0', u'System', u'System1', u'Menu', u'SystemMenu']
| | child_window(title="System", auto_id="MenuBar", control_type="MenuBar")
| | |
| | | MenuItem - 'System' (L696, T526, R718, B548)
| | | [u'System2', u'MenuItem', u'SystemMenuItem']
| | | child_window(title="System", control_type="MenuItem")
| |
| | Button - 'Close' (L1024, T519, R1058, B549)
| | [u'CloseButton', u'Close', 'Button5']
| | child_window(title="Close", control_type="Button")
(, iTunes !), depth
(): depth=1
, depth=2
, . child_window
.
. WireShark ( Qt5 ; GUI, scapy.Sniffer
scapy). MS Paint Ribbon .
, : explorer.exe Chrome Google Drive ( ).
, , (hot keys) :
hook_and_listen.py.
, . . . MS UI Automation "-" ( ), "uia" . Linux AT-SPI ( mouse
keyboard
python-xlib 0.6.x).
Python, - , . - . . (QuantifiedCode, Codacy Landscape) ( AppVeyor) 95%.
, , !
StackOverflow ( SO) . Gitter'.
open-source GUI . Autohotkey ( ) PyAutoGUI ( Al Sweigart: "Automate the Boring Stuff with Python" ).