-

   rss_rss_hh_new

 - e-mail

 

 -

 LiveInternet.ru:
: 17.03.2011
:
:
: 51

:


GUI Python + pywinauto: c MS UI Automation

, 13 2017 . 10:28 +

Python pywinauto open source GUI Windows. :


  • MS UI Automation. , : WinForms, WPF, Qt5, Windows Store (UWP) , Windows.
  • / ( : "win32" "uia"). -.
  • Win32 (hot keys pyHook).

, 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.


Accessibility


[+] , .. , , .
[+] => .
[+] , , .. 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 . . , . , .


backdoor (a.k.a. )


- testability. , TCP , : , .. , .


accessibility


Win32 API


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).


Microsoft UI Automation


: 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.


AT-SPI


, 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-.


Apple Accessibility API


MacOS AppleScript. - Python, , ObjectiveC. , , MacOS 10.6 pyobjc. pywinauto.


: Apple Script, ATOMac, pyatom. LDTP, . iTunes macOs, . : ( waitFor*). , , .




pywinauto


GUI (, Spy tool). : , . :


  • Spy++ Visual Studio, Express Community Edition. Win32 API. AutoIt Window Info.
  • Inspect.exe Windows SDK. , 64- Windows C:\Program Files (x86)\Windows Kits\\bin\x64. UI Automation MS AA (Active Accessibility, UI Automation).

, , . Application.


  • backend="win32" , MFC, WTL, VB6 legacy .
  • backend="uia" MS UI Automation: WPF WinForms; Delphi Windows Store ; Qt5 Java . , Inspect.exe , . , UI Automation (Mozilla , --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')


? , . , , .


  1. (, ): app.Properties.OK.click()
  2. : app.Properties.OKButton.click()
  3. : app.Properties.Button3.click() ( Button0 Button1 , Button2 , )
  4. ( ) : app.OpenDialog.FileNameEdit.set_text("") ( )
  5. : 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" ).

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/323962/


: [1] []
 

:
: 

: ( )

:

  URL