Asztali GUI automatizálása Python + pywinauto: hogyan barátkozhatunk össze az MS UI Automation-nel

Python könyvtár pywinauto — ez egy nyílt forráskódú projekt asztali GUI alkalmazások automatizálására Windows rendszeren. Az utolsó két évben új, jelentős funkciók jelentek meg benne:

  • Támogatás a MS UI Automation technológiához. A felület változatlan maradt, és most támogatja: WinForms, WPF, Qt5, Windows Store (UWP) és így tovább — szinte minden, ami a Windows rendszeren elérhető.
  • Hátterek/plugin rendszer (jelenleg kettő van a motorban: alapértelmezett "win32" és új "uia"). Tovább fokozatosan haladunk a platformfüggetlenség felé.
  • Win32 horgok az egér és billentyűzet számára (hotkeyek a pyHook stílusában).

Emellett rövid áttekintést adunk arról, mi áll rendelkezésre az open source közösségben az asztali automatizálás terén (anélkül, hogy komoly összehasonlítást tennénk).

Ez a cikk részben a SQA Days 20 konferencián tartott előadásból készült (videófelvételt és diák), részben az orosz verziója Getting Started Guide a pywinautohoz.

Kezdjük egy rövid áttekintéssel az open source területen. Az asztali GUI alkalmazások esetében a helyzet némileg bonyolultabb, mint a web esetében, ahol van a Selenium. Íme a főbb megközelítések:

Koordináta módszer

Hardcode-oljuk a kattintási pontokat, remélve a sikeres találatokban.
[+] Platformfüggetlen, könnyen megvalósítható.
[+] Könnyen megvalósítható "record-replay" tesztfelvétel.
[-] A leginstabilabb a képernyő felbontásának, témáknak, betűtípusoknak, ablakméreteknek stb. változására.
[-] Hatalmas erőfeszítéseket igényel a karbantartás, gyakran egyszerűbb újratermelni a teszteket vagy manuálisan tesztelni.
[-] Csak az akciókat automatizálja, a verifikációhoz és az adatok kiemeléséhez más módszerek szükségesek.

Eszközök (platformfüggetlenek): autopy, PyAutoGUI, PyUserInput és sok más. Általában a bonyolultabb eszközök tartalmazzák ezt a funkcionalitást (nem mindig platformfüggetlenül).

Érdemes megjegyezni, hogy a koordináta módszer kiegészítheti a többi megközelítést. Például egyedi grafikák esetén lehet kattintani relatív koordinátákra (az ablak/elem bal felső sarkából kiindulva, nem az egész képernyőről) — általában ez elegendően megbízható, különösen, ha figyelembe vesszük az elem teljes hosszát/szélességét (akkor a különböző képernyőfelbontás sem akadály).

Egy másik lehetőség: csak egy gépet kijelölni a tesztekhez, stabil beállításokkal (nem cross-platform, de bizonyos esetekben megfelel).

Referenciaképek felismerése

[+] Cross-platform
[+-] Relatíve megbízható (jobb, mint a koordináta módszer), de mégis ügyességet igényel.
[-+] Relatíve lassú, mivel CPU erőforrásokat igényel a felismerési algoritmusokhoz.
[-] A szövegfelismerés (OCR) általában nem beszélhető => nem lehet szöveges adatokat kinyerni. Tudomásom szerint a létező OCR megoldások nem túl megbízhatóak erre a feladatra, és széleskörű alkalmazásuk nincs (várom a kommenteket, ha ez már nem így van).

könyvtár támogat. Sikuli, Lackey (Sikuli-kompatibilis, tiszta Python-on), PyAutoGUI.

Accessibility technológiák

[+] A legmegbízhatóbb módszer, mert lehetővé teszi a szöveg szerinti keresést, függetlenül attól, hogyan rajzolja ki a rendszer vagy keretrendszer.
[+] Lehetővé teszi a szöveges adatok kinyerését => egyszerűbbé teszi a tesztek eredményeinek ellenőrzését.
[+] Általában a leggyorsabb, mert szinte nem használ CPU erőforrásokat.
[-] Nehéz cross-platform eszközt létrehozni: szinte minden nyílt forráskódú könyvtár csak egy-két akadálymentesítési technológiát támogat. Windows/Linux/MacOS-t senki nem támogat teljes mértékben, kivéve a fizetős megoldásokat, mint a TestComplete, UFT vagy Squish.
[-] Nem mindig érhető el egy ilyen technológia. Például a VirtualBox-ban lévő betöltő képernyő teszteléséhez elkerülhetetlen a képfelismerés. De sok klasszikus esetben az akadálymentesítés megközelítés mégis alkalmazható. Erről fog szólni a következő rész.

könyvtár támogat. TestStack.White C#-on, Winium.Desktop C#-on (Selenium kompatibilis), MS WinAppDriver C#-on (Appium kompatibilis), pywinauto, pyatom (LDTP-vel kompatibilis), Python-UIAutomation-for-Windows, RAutomation Ruby-n, LDTP (Linux Desktop Testing Project) és annak Windows verziója Cobra.

A LDTP talán az egyetlen cross-platform nyílt forráskódú eszköz (pontosabban a könyvtárak családja) az akadálymentesítési technológiák alapján. Azonban nem túl népszerű. Én nem használtam, de a visszajelzések szerint a felülete nem a legkényelmesebb. Ha van pozitív értékelés, kérlek, oszd meg a kommentekben.

Teszt backdoor (más néven belső kerékpár)

Cross-platform alkalmazások esetén a fejlesztők gyakran belső mechanizmust készítenek a tesztelhetőség biztosítására. Például létrehoznak egy segéd TCP szervert az alkalmazásban, a tesztek ehhez csatlakoznak, és szöveges parancsokat küldenek: mit kell megnyomni, honnan kell adatokat szerezni, stb. Megbízható, de nem univerzális.

Főbb asztali hozzáférhetőségi technológiák

A régi, jó Win32 API

A legtöbb Windows alkalmazás, amelyet a WPF és a Windows Store megjelenése előtt írtak, valamilyen módon a Win32 API-ra épül. Konkrétan az MFC, WTL, C++ Builder, Delphi, VB6 - mindezek az eszközök a Win32 API-t használják. Még a Windows Forms is - nagymértékben Win32 API kompatibilis.

könyvtár támogat. AutoIt (VB-hez hasonló) és Python wrapper pyautoit, AutoHotkey (saját nyelv, van IDispatch COM interfész), pywinauto (Python), RAutomation (Ruby), win32-autogui (Ruby).

Microsoft UI Automation

A legfontosabb előny: a MS UI Automation technológia a Windows GUI alkalmazások túlnyomó többségét támogatja, néhány kivétellel. Probléma: nem sokkal könnyebb elsajátítani, mint a Win32 API-t. Különben senki sem készítene wrappers-t köré.

Valójában ez egy testreszabott COM interfészek készlete (főleg, UIAutomationCore.dll), és rendelkezik .NET burkolattal is, namespace System.Windows.Automation. Egyébként van benne egy behozott hiba, ami miatt egyes UI elemek hiányozhatnak. Ezért jobb közvetlenül a UIAutomationCore.dll-t használni (ha hallottál a C#-os UiaComWrapperről, az ez).

A COM interfészek változatai:

(1) Alap IUknown - „a gonosz gyökere”. A legalacsonyabb szint, nem éppen felhasználóbarát.
(2) IDispatch és származékai (például, Excel.Application), amelyeket Pythonban a win32com.client csomagon keresztül lehet használni (a pyWin32 része). A legkényelmesebb és legszebb megoldás.
(3) Testreszabott interfészek, amelyeket a külső Python csomag comtypes.

könyvtár támogat. TestStack.White C#-on, pywinauto 0.6.0+, Winium.Desktop C#-on, Python-UIAutomation-for-Windows (a UIAutomationCore.dll feletti C-s wrapper forráskódja nem nyilvános), RAutomation Rubyban.

AT-SPI

Annak ellenére, hogy szinte minden Linux családba tartozó operációs rendszer az X Window System-re épül (a Fedora 25-ben az „ikszeket” Waylandra cserélte), az „ikszek” csak a felső szintű ablakokkal és az egér/kibővített billentyűzet lehetőségekkel működnek. A gombok, listaboxok és hasonlók részletesebb lebonyolításához az AT-SPI technológia létezik. A legnépszerűbb ablakkezelők rendelkeznek egy úgynevezett AT-SPI registry démonnal, amely biztosítja az alkalmazások számára az automatizálható GUI-t (legalább a Qt és GTK támogatott).

könyvtár támogat. pyatspi2.

A pyatspi2, véleményem szerint, túl sok függőséget tartalmaz, mint a PyGObject. Maga a technológia egy szokásos dinamikus könyvtár formájában érhető el, libatspi.so. Ezzel együtt Referencia Kézikönyv. A pywinauto könyvtárhoz tervezzük az AT-SPI támogatását megvalósítani így: a libatspi.so betöltésével és a ctypes modullal. Csak egy kis probléma van a megfelelő verzió használatában, mert a GTK+ és Qt alkalmazások számára ezek kissé eltérőek. A pywinauto 0.7.0 várható kiadása a Linux teljes támogatásával várható 2018 első felében.

Apple Accessibility API

A MacOS saját automatizálási nyelve az AppleScript. Hasonló megoldás megvalósításához Pythonban természetesen ObjectiveC függvények használatára van szükség. Úgy tűnik, hogy már MacOS 10.6-tól kezdődően a telepített Python csomagja a pyobjc. Ez megkönnyíti a jövőbeli támogatáshoz szükséges függőségek listáját a pywinauto-hoz.

Eszközök: Az Apple Script nyelve mellett érdemes figyelmet fordítani ATOMac, más néven pyatom. Ez az LDTP-vel kompatibilis interfésze, de egyúttal önálló könyvtár is. Rajta található példa az iTunes automatizálására macOS-en, amelyet a diákum írt. Van egy ismert probléma: a rugalmas időzítések nem működnek (a waitFor*módszerek). De összességében, elég jó cucc.

Hogyan kezdjünk el dolgozni a pywinauto-val

Először is érdemes megragadni egy GUI objektum inspektort (amit Spy tool-nak hívnak). Ez segít az alkalmazás belsejének tanulmányozásában: hogyan épül fel az elemek hierarchiája, milyen tulajdonságok érhetők el. A legismertebb objektum-ellenőrök közé tartoznak:

  • Spy++ — a Visual Studio, beleértve az Express-t vagy a Community Edition-t, csomagjában található. Win32 API-t használ. Ismert klónja a AutoIt Window Info.
  • Inspect.exe — a Windows SDK része. Ha telepítve van, akkor egy 64 bites Windows-on a következő könyvtárban található C:Program Files (x86)Windows Kitsbinx64. Az inspectorban a UI Automation módot kell választani a helyett, hogy MS AA (Active Accessibility, a UI Automation elődje) legyen.

Miután átvizsgáltuk az alkalmazást, kiválasztjuk a hátteret, amelyet használni fogunk. Elég, ha a háttér nevét megadjuk az Application objektum létrehozásakor.

  • backend=»win32″ — egyelőre az alapértelmezett, jól működik MFC, WTL, VB6 és egyéb örökölt alkalmazásokkal.
  • backend=»uia» — az új háttér az MS UI Automation-hoz: tökéletesen működik WPF és WinForms esetén; szintén jól alkalmas Delphi és Windows Store alkalmazások számára; működik Qt5-tel és néhány Java alkalmazással. Egyébként, ha az Inspect.exe látja az elemeket és azok tulajdonságait, akkor ez a háttér alkalmas. Alapvetően a legtöbb böngésző is támogatja a UI Automation-t (a Mozilla alapértelmezés szerint, míg a Chrome-ot indításkor meg kell etetni a parancssori kulccsal --force-renderer-accessibility, hogy láthassuk az elemeket az Inspect.exe ablakban). Természetesen, a Selenium-nal való verseny ebben a területen valószínűleg nem lehetséges. Csak egy újabb módja a böngészővel való munkának (hasznos lehet a cross-termék forgatókönyvnél).

Belépési pontok az automatizáláshoz

Az alkalmazás elég jól meg van ismerve. Ideje létrehozni egy Application objektumot, és elindítani, vagy csatlakozni a már futóhoz. Ez nem csupán a szokásos osztály klónja. subprocess.Popen, nevezetesen egy bevezető objektum, amely minden tevékenységedet a folyamat határai közé szorítja. Ez nagyon hasznos, ha az alkalmazás több példányát futtatod, és a többi alkalmazást nem akarod érinteni.

from pywinauto.application import Application
app = Application(backend="uia").start('notepad.exe')

# Leírjuk az ablakot, amelyet meg szeretnénk találni a Notepad.exe folyamatban
dlg_spec = app.UntitledNotepad
# várunk, amíg az ablak valóban megjelenik
actionable_dlg = dlg_spec.wait('visible')

Ha egyszerre több alkalmazást szeretnél irányítani, akkor segít a Asztali. Például a Win10-es kalkulátor esetében az elemek hierarchiája több folyamatra is kiterjed (nem csak calc.exe). Tehát elkerülhetetlen a Asztali .

from subprocess import Popen
from pywinauto import Desktop

Popen('calc.exe', shell=True)
dlg = Desktop(backend="uia").Calculator
dlg.wait('visible')

A gyökérobjektum (Alkalmazás vagy Asztali) — ez az egyetlen hely, ahol meg kell adni a backendet. Minden más átláthatóan illeszkedik a "specifikáció->wrapper" koncepcióba, amiről később olvashatsz.

Ablakok/elemek specifikációi

Ez a fő koncepció, amelyre a pywinauto interfésze épül. Leírhatod az ablakot/elemet közelítően vagy részletesebben, akár ha még nem is létezik, vagy már bezárták. Az ablak specifikációja (objektum WindowSpecification) tartalmazza azokat a kritériumokat, amelyek alapján valódi ablakot vagy elemet kell keresni.

Példa egy részletes ablak specifikációjára:

>>> dlg_spec = app.window(title='Untitled - Notepad')

>>> dlg_spec


>>> dlg_spec.wrapper_object()

Az ablak keresése a .wrapper_object()hívásával történik. Ez visszaad egy "wrapper"-t a valódi ablakhoz/elemhez, vagy dob egy ElementNotFoundError (néha ElementAmbiguousError, ha több elemet találnak, tehát pontosítani kell a keresési kritériumokat). Ez a "wrapper" már képes végrehajtani bizonyos műveleteket az elemmel, vagy adatokat kinyerni belőle.

A Python elrejtheti a hívást, így a végső kód rövidebb lesz. Javasoljuk, hogy ezt csak a hibakereséshez használd. A következő két sor teljesen ugyanazt csinálja: .wrapper_object()dlg_spec.wrapper_object().minimize() # debugging dlg_spec.minimize() # production

Számos keresési kritérium létezik az ablak specifikációhoz. Íme néhány példa:

A lehetséges kritériumok teljes listája a

# могут иметь несколько уровней
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(…) függvény dokumentációjában található. A Python megkönnyíti az ablak specifikációk létrehozását, és dinamikusan ismeri fel az objektum attribútumait (a.

A mágikus hozzáférés attribútum és kulcs alapján

__getattribute__ metódus felül van definiálva)). Természetesen az attribútum nevére ugyanazok a korlátozások vonatkoznak, mint bármely változó nevére (nem lehet szóköz, vessző és egyéb speciális karakterek). Szerencsére a pywinauto úgynevezett „legjobb egyezés” keresési algoritmusát használja, amely ellenáll a gépelési hibáknak és a kisebb eltéréseknek.

app.NemCímzettJegyzettömb
# ugyanaz, mint
app.window(best_match='NemCímzettJegyzettömb')

Ha mégis Unicode karakterláncokra van szükség (például orosz nyelv esetén), akkor szóközök stb. használatával hozzáférhet a kulcs alapján (mintha ez egy hagyományos szótár lenne):

app['Untitled - Notepad']
# ugyanaz, mint
app.window(best_match='Untitled - Notepad')

Öt szabály a mágikus nevekhez

Hogyan tudhatjuk meg az etalon mágikus neveket? Azokat, amelyeket az elemhez rendeltek a keresés előtt. Ha a megadott név eléggé hasonlít az etalonra, akkor az elem megtalálható.

  1. Cím alapján (szöveg, név): app.Properties.OK.click()
  2. Elem szövege és típusa alapján: app.Properties.OKButton.click()
  3. Típus és szám alapján: app.Properties.Button3.click() (nevek Button0 és Button1 az első megtalált elemhez kötődnek, Button2 — a másodikhoz, és tovább már sorrendben — így alakult ez történetileg)
  4. Statikus szöveg (balról vagy felülről) és típusa alapján: app.OpenDialog.FileNameEdit.set_text("") (hasznos dinamikus szöveget tartalmazó elemeknél)
  5. Típus és belső szöveg alapján: app.Properties.TabControlSharing.select("General")

Általában két-három szabályt alkalmaznak egyszerre, ritkán többet. Annak ellenőrzésére, hogy pontosan milyen nevek érhetők el az egyes elemek számára, használhatja a print_control_identifiers(). Ez a parancs ki tudja nyomtatni az elemek fáját a képernyőre és fájlba is. Minden elem esetében kiírja az etalon mágikus neveit. Innen részletesebb specifikációkat is átmásolhat a gyermekelemekről. Az eredmény a szkriptben így fog kinézni:

app.Properties.child_window(title="Contains:", auto_id="13087", control_type="Edit")

Az elemek fája — általában elég hosszú szöveg.

>>> app.Properties.print_control_identifiers()

Vezérlő azonosítók:

Dialógus - 'Windows NT Tulajdonságok'    (L688, T518, R1065, B1006)
[u'Windows NT TulajdonságokDialógus', u'Dialógus', u'Windows NT Tulajdonságok']
child_window(title="Windows NT Tulajdonságok", control_type="Window")
   |
   | Kép - ''    (L717, T589, R749, B622)
   | [u'', u'0', u'Kép1', u'Kép0', 'Kép', u'1']
   | child_window(auto_id="13057", control_type="Image")
   |
   | Kép - ''    (L717, T630, R1035, B632)
   | ['Kép2', u'2']
   | child_window(auto_id="13095", control_type="Image")
   |
   | Szerkesztés - 'Mappa neve:'    (L790, T596, R1036, B619)
   | [u'3', 'Szerkesztés', u'Szerkesztés1', u'Szerkesztés0']
   | child_window(title="Mappa neve:", auto_id="13156", control_type="Edit")
   |
   | Statikus - 'Típus:'    (L717, T643, R780, B658)
   | [u'Típus:Statikus', u'Statikus', u'Statikus1', u'Statikus0', u'Típus:']
   | child_window(title="Típus:", auto_id="13080", control_type="Text")
   |
   | Szerkesztés - 'Típus:'    (L790, T643, R1036, B666)
   | [u'4', 'Szerkesztés2', u'Típus:Szerkesztés']
   | child_window(title="Típus:", auto_id="13059", control_type="Edit")
   |
   | Statikus - 'Hely:'    (L717, T669, R780, B684)
   | [u'Hely:Statikus', u'Hely:', u'Statikus2']
   | child_window(title="Hely:", auto_id="13089", control_type="Text")
   |
   | Szerkesztés - 'Hely:'    (L790, T669, R1036, B692)
   | ['Szerkesztés3', u'Hely:Szerkesztés', u'5']
   | child_window(title="Hely:", auto_id="13065", control_type="Edit")
   |
   | Statikus - 'Méret:'    (L717, T695, R780, B710)
   | [u'Méret:Statikus', u'Méret:', u'Statikus3']
   | child_window(title="Méret:", auto_id="13081", control_type="Text")
   |
   | Szerkesztés - 'Méret:'    (L790, T695, R1036, B718)
   | ['Szerkesztés4', u'6', u'Méret:Szerkesztés']
   | child_window(title="Méret:", auto_id="13064", control_type="Edit")
   |
   | Statikus - 'Méret lemezen:'    (L717, T721, R780, B736)
   | [u'Méret lemezen:', u'Méret lemezen:Statikus', u'Statikus4']
   | child_window(title="Méret lemezen:", auto_id="13107", control_type="Text")
   |
   | Szerkesztés - 'Méret lemezen:'    (L790, T721, R1036, B744)
   | ['Szerkesztés5', u'7', u'Méret lemezen:Szerkesztés']
   | child_window(title="Méret lemezen:", auto_id="13106", control_type="Edit")
   |
   | Statikus - 'Tartalmaz:'    (L717, T747, R780, B762)
   | [u'Tartalmaz:1', u'Tartalmaz:0', u'Tartalmaz:Statikus', u'Statikus5', u'Tartalmaz:']
   | child_window(title="Tartalmaz:", auto_id="13088", control_type="Text")
   |
   | Szerkesztés - 'Tartalmaz:'    (L790, T747, R1036, B770)
   | [u'8', 'Szerkesztés6', u'Tartalmaz:Szerkesztés']
   | child_window(title="Tartalmaz:", auto_id="13087", control_type="Edit")
   |
   | Kép - 'Tartalmaz:'    (L717, T773, R1035, B775)
   | [u'Tartalmaz:Kép', 'Kép3', u'Tartalmaz:2']
   | child_window(title="Tartalmaz:", auto_id="13096", control_type="Image")
   |
   | Statikus - 'Létrehozva:'    (L717, T786, R780, B801)
   | [u'Létrehozva:', u'Létrehozva:Statikus', u'Statikus6', u'Létrehozva:1', u'Létrehozva:0']
   | child_window(title="Létrehozva:", auto_id="13092", control_type="Text")
   |
   | Szerkesztés - 'Létrehozva:'    (L790, T786, R1036, B809)
   | [u'Létrehozva:Szerkesztés', 'Szerkesztés7', u'9']
   | child_window(title="Létrehozva:", auto_id="13072", control_type="Edit")
   |
   | Kép - 'Létrehozva:'    (L717, T812, R1035, B814)
   | [u'Létrehozva:Kép', 'Kép4', u'Létrehozva:2']
   | child_window(title="Létrehozva:", auto_id="13097", control_type="Image")
   |
   | Statikus - 'Attribútumok:'    (L717, T825, R780, B840)
   | [u'Attribútumok:Statikus', u'Statikus7', u'Attribútumok:']
   | child_window(title="Attribútumok:", auto_id="13091", control_type="Text")
   |
   | Jelölőnégyzet - 'Csak olvasható (Csak a mappában lévő fájlokra vonatkozik)'    (L790, T825, R1035, B841)
   | [u'Jelölőnégyzet0', u'Jelölőnégyzet1', 'Jelölőnégyzet', u'Csak olvasható (Csak a mappában lévő fájlokra vonatkozik)Jelölőnégyzet', u'Csak olvasható (Csak a mappában lévő fájlokra vonatkozik)']
   | child_window(title="Csak olvasható (Csak a mappában lévő fájlokra vonatkozik)", auto_id="13075", control_type="CheckBox")
   |
   | Jelölőnégyzet - 'Rejtett'    (L790, T848, R865, B864)
   | ['Jelölőnégyzet2', u'RejtettJelölőnégyzet', u'Rejtett']
   | child_window(title="Rejtett", auto_id="13076", control_type="CheckBox")
   |
   | Gomb - 'Haladó...'    (L930, T845, R1035, B868)
   | [u'Haladó...', u'Haladó...Gomb', 'Gomb', u'Gomb1', u'Gomb0']
   | child_window(title="Haladó...", auto_id="13154", control_type="Button")
   |
   | Gomb - 'OK'    (L814, T968, R889, B991)
   | ['Gomb2', u'OK', u'OKGomb']
   | child_window(title="OK", auto_id="1", control_type="Button")
   |
   | Gomb - 'Mégsem'    (L895, T968, R970, B991)
   | ['Gomb3', u'MégsemGomb', u'Mégsem']
   | child_window(title="Mégsem", auto_id="2", control_type="Button")
   |
   | Gomb - 'Alkalmaz'    (L976, T968, R1051, B991)
   | ['Gomb4', u'AlkalmazGomb', u'Alkalmaz']
   | child_window(title="Alkalmaz", auto_id="12321", control_type="Button")
   |
   | TabControl - ''    (L702, T556, R1051, B962)
   | [u'10', u'TabControlMegosztás', u'TabControlElőző verziók', u'TabControlBiztonság', u'TabControl', u'TabControlTestreszabás']
   | child_window(auto_id="12320", control_type="Tab")
   |    |
   |    | TabItem - 'Általános'    (L704, T558, R753, B576)
   |    | [u'ÁltalánosTabItem', 'TabItem', u'Általános', u'TabItem0', u'TabItem1']
   |    | child_window(title="Általános", control_type="TabItem")
   |    |
   |    | TabItem - 'Megosztás'    (L753, T558, R801, B576)
   |    | [u'Megosztás', u'MegosztásTabItem', 'TabItem2']
   |    | child_window(title="Megosztás", control_type="TabItem")
   |    |
   |    | TabItem - 'Biztonság'    (L801, T558, R851, B576)
   |    | [u'Biztonság', 'TabItem3', u'BiztonságTabItem']
   |    | child_window(title="Biztonság", control_type="TabItem")
   |    |
   |    | TabItem - 'Előző Verziók'    (L851, T558, R947, B576)
   |    | [u'Előző VerziókTabItem', u'Előző Verziók', 'TabItem4']
   |    | child_window(title="Előző Verziók", control_type="TabItem")
   |    |
   |    | TabItem - 'Testreszabás'    (L947, T558, R1007, B576)
   |    | [u'TestreszabásTabItem', 'TabItem5', u'Testreszabás']
   |    | child_window(title="Testreszabás", control_type="TabItem")
   |
   | TitleBar - 'Nincs'    (L712, T521, R1057, B549)
   | ['TitleBar', u'11']
   |    |
   |    | Menüsor - 'Rendszer'    (L696, T526, R718, B548)
   |    | [u'Rendszer0', u'Rendszer', u'Rendszer1', u'Menü', u'RendszerMenü']
   |    | child_window(title="Rendszer", auto_id="MenuBar", control_type="MenuBar")
   |    |    |
   |    |    | Menüelem - 'Rendszer'    (L696, T526, R718, B548)
   |    |    | [u'Rendszer2', u'MenüElem', u'RendszerMenüElem']
   |    |    | child_window(title="Rendszer", control_type="MenuItem")
   |    |
   |    | Gomb - 'Bezárás'    (L1024, T519, R1058, B549)
   |    | [u'BezárásGomb', u'Bezárás', 'Gomb5']
   |    | child_window(title="Bezárás", control_type="Button")

Bizonyos esetekben a teljes fa nyomtatása lassíthat, például az iTunesban egyetlen fül alatt akár három ezer elem is lehet! De használhatjuk a paramétert depth (mélység): depth=1 — az adott elem, depth=2 — csak a közvetlen gyermekek, és így tovább. Ezt a specifikációkban is megadhatjuk, amikor létrehozzuk a child_window.

Példák

Folyamatosan bővítjük a példák listáját a repóban. A legfrissebb közül említést érdemel a WireShark hálózati elemző automatizálása (ez jó példa a Qt5 alkalmazásra; bár ezt a feladatot GUI nélkül is megoldhatjuk, mivel ott van a scapy.Sniffer a Python csomagból scapy). Van egy példa az MS Paint automatizálására is a Ribbon eszköztárral.

Még egy nagyszerű példa, amelyet a diákjaim írtak: az explorer.exe-ből egy fájl Chrome oldalra való húzása a Google Drive számára (ez majd később bekerül a fő repóba).

És természetesen van egy példa a billentyűzet események (hotkey) és az egér figyelésére:
hook_and_listen.py.

Köszönetnyilvánítások

Külön köszönet azoknak, akik folyamatosan segítenek a projekt fejlesztésében. Számomra és Valentina ez egy állandó hobbivá vált. Két diákom az NNGU-ból nemrégiben védte meg a szakdolgozatát ebben a témában. Alexander nagy mértékben hozzájárult az MS UI Automation támogatásához, és nemrég kezdett el automatikus kódgenerálót készíteni a „felvétel-lejátszás” elv alapján szöveges tulajdonságok alapján (ez a legbonyolultabb funkció), egyelőre csak a „uia” backendhez. Iván új backendet fejleszt Linux alatt AT-SPI alapokra (a mouse és keyboard a következő alapján python-xlib — már a 0.6.x kiadásokban).

Mivel már régen tartok speciális kurzust a Python automatizálásról, a mesterszakos hallgatók közül egyesek házi feladatokat végeznek, kis funkciók vagy automatizálási példák megvalósításával. Néhány kulcsfontosságú dolgot szintén diákok fedeztek fel a kutatások során. Bár néha nagyon figyelni kell a kód minőségére. Ebben sokat segítenek a statikus elemzők (QuantifiedCode, Codacy és Landscape) és az automatikus tesztek a felhőben (AppVeyor szolgáltatás) a kód 95%-ot meghaladó lefedettségével.

Köszönöm mindenkinek, aki véleményt ír, hibákat jelent, és küld bugjavítási kérelmeket!

Sok jó cikk és publikáció létezik a kustomize-ról. Íme néhány, amit különösen hasznosnak találtam:

A kérdéseket a StackOverflow címkén figyeljük (nemrégiben megjelent egy címke az orosz SO verziójában, ennek eredményeként a lekérdezések olyan formát öltenek, mint a fent említett. a Toster kulcsszava alapján. Létezik orosz nyelvű chat a Gitteren.

Minden hónapban frissítjük a nyílt forráskódú könyvtárak értékelését GUI teszteléshez. Csillagok számát tekintve a GitHubon csak az Autohotkey nő gyorsabban (nekik nagyon nagy közösségük és hosszú történetük van) és a PyAutoGUI (nagyrészt Al Sweigart: «Automate the Boring Stuff with Python» és más könyveinek népszerűségének köszönhetően).

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster