Automatiseerime töölaual GUI kasutades Pythonit + pywinauto: kuidas sõbruneda MS UI Automatisatsiooniga

Python raamatukogu pywinauto — see on open source projekt Windowsi töölaua GUI rakenduste automatiseerimiseks. Viimase kahe aasta jooksul on lisandunud sinna uusi suuri funktsioone:

  • Toetatakse MS UI Automation tehnoloogiat. Liides on endine, ja nüüd toetatakse: WinForms, WPF, Qt5, Windows Store (UWP) jne — peaaegu kõike, mis Windowsis olemas on.
  • Tagumise süsteemi/pluginite süsteem (praegu on neid kaks: vaikimisi "win32" ja uus "uia"). Liikume sujuvalt edasi platvormideüleste lahenduste suunas.
  • Win32 hiire ja klaviatuuri konksud (kuumklahvid nagu pyHookis).

Teeme ka väikese ülevaate open source'ist töölaua automatiseerimiseks (ilma tõsise võrdluseta).

See artikkel on osaliselt ülekanne SQA Days 20 konverentsilt Minskis (videoklipp ja slaidid), osaliselt vene versioon Getting Started Guide pywinauto jaoks.

Alustame kiire ülevaatega avatud lähtekoodist selles valdkonnas. Laua- GUI rakenduste puhul on kõik natuke keerulisem kui veebis, kus on Selenium. Siin on peamised lähenemisviisid:

Koordinaatmudel

Koodime klikkide punktid, loodame õnnestumistele.
[+] Üksnes platvormide vahel, kergesti rakendatav.
[+] Lihtne teha "record-replay" testide salvestust.
[-] Kõige ebastabiilsem ekraani eraldusvõime, teemade, fontide, aknasuuruste jne muutumise osas.
[-] Suured pingutused toe osas, tihti on lihtsam testid algusest peale uuesti genereerida või testida käsitsi.
[-] Automatiseerib ainult toimingud, validatsiooni ja andmete väljavõtmiseks on teised meetodid.

Tööriistad (platvormide vahel): autopy, PyAutoGUI, PyUserInput ja paljusid teisi. Üldiselt sisaldavad keerukamad tööriistad seda funktsionaalsust (kuid mitte alati platvormide vahel).

Tasub märkida, et koordinaatmeetod võib täiendada teisi lähenemisviise. Näiteks võib kohandatud graafika jaoks klõpsata suhtelistele koordinaatidele (vasakust ülanurgast akna/elemendi, mitte kogu ekraani osas) — see on tavaliselt piisavalt usaldusväärne, eriti kui arvestada kogu elemendi pikkust/laiust (siis ei takista ka erinev ekraani eraldusvõime).

Teine võimalus: testimiseks valida vaid üks masin stabiilsete seadistustega (mitte ristplatvormne, kuid teatud juhtudel sobib).

Malli piltide tuvastamine

[+] Ristplatvormne
[+-] Suhteliselt usaldusväärne (parem kui koordinaatmeetod), kuid siiski vajab nippe.
[-+] Suhteliselt aeglane, kuna vajab CPU ressursse tunnustamisalgoritmide jaoks.
[-] Tekstituvastus (OCR) ei ole tavaliselt teema => tekstilisi andmeid ei saa kätte. Mida rohkem ma tean, ei ole olemasolevad OCR lahendused selle tüüpi ülesannete jaoks eriti usaldusväärsed ja laialdaselt kasutuses (teretulemast kommentaaridesse, kui see enam nii ei ole).

Tööriistad: Sikuli, Lackey (Sikuli ühilduv, puhas Python), PyAutoGUI.

Juurdepääsetavuse tehnoloogiad

[+] Kõige usaldusväärsem meetod, kuna võimaldab otsida teksti, sõltumata sellest, kuidas see süsteemi või raamistikuga joonistatud on.
[+] Võimaldab ekstraktida tekstilisi andmeid => lihtsustab testitulemuste verifitseerimist.
[+] Üldiselt on see kõige kiirem, kuna tarbib peaaegu mitte mingisuguseid CPU ressursse.
[-] Raskesti on teha ristplatvormi tööriista: kõik open-source raamatukogud toetavad üks või kaks ligipääsetavustehnoloogiat. Windows/Linux/MacOS ei toeta täielikult keegi muu kui tasulised nagu TestComplete, UFT või Squish.
[-] Selline tehnoloogia ei pruugi alati üldse saadaval olla. Näiteks laadimisekraani testimine VirtualBoxis — selleks on ilma pildituvastuseta keeruline hakkama saada. Siiski on paljude klassikaliste juhtumite puhul ligipääsetavuse lähenemine rakendatav. Selle kohta käib edasi jutt.

Tööriistad: TestStack.White C#-s, Winium.Desktop C#-s (Seleniumi ühilduv), MS WinAppDriver C#-s (Appiumi ühilduv), pywinauto, pyatom (ühilduv LDTP-ga), Python-UIAutomation-for-Windows, RAutomation Rubys, LDTP (Linux Desktop Testing Project) ja selle Windowsi versioon Cobra.

LDTP on ilmselt ainus ristplatvormi open-source tööriist (täpsemalt ligipääsetavustehnoloogiatele tuginev raamatukogude perekond). Siiski ei ole see väga populaarne. Olen seda ise kasutanud, kuid tagasiside põhjal ei ole selle liidese kasutamine kõige mugavam. Kui on positiivset tagasisidet, palun jagage kommentaarides.

Testbackdoor (tuntud ka kui sisemine jalgratas)

Üldiselt arendavad arendajad ristplatvormsete rakenduste jaoks sageli sisemist mehhanismi testimise tagamiseks. Näiteks luuakse rakenduses teenindav TCP server, millele testid ühenduvad ja saadavad tekstikäske: mida vajutada, kust andmeid võtta jne. Usaldusväärne, kuid mitte universaalne.

Peamised töölaua juurdepääsetavuse tehnoloogiad

Hea vana Win32 API

Enamik Windowsi rakendusi, mis on kirjutatud enne WPF-i ja seejärel Windows Store'i, on mingil moel üles ehitatud Win32 API-le. Täpsemalt: MFC, WTL, C++ Builder, Delphi, VB6 — kõik need tööriistad kasutavad Win32 API-d. Ieven Windows Forms on suuresti Win32 API-ga ühilduv.

Tööriistad: AutoIt (sarnaneb VB-le) ja Pythoni wrapper pyautoit, AutoHotkey (oma keel, on IDispatch COM liides), pywinauto (Python), RAutomation (Ruby), win32-autogui (Ruby).

Microsoft UI Automatisatsioon

Peamine eelis: MS UI Automation tehnoloogia toetab enamiku Windowsi GUI rakendustest, välja arvatud harvad erandid. Probleem: see ei ole palju kergem õppida kui Win32 API. Muidu keegi ei teeks selle ümber wrapper'it.

Tegelikult on see kogum kohandatud COM liideseid (peamiselt, UIAutomationCore.dll), samuti on .NET-i ümbritseja kujul namespace System.Windows.Automation. Lisaks, sellel on sisse toodud bugg, mille tõttu mõned UI elemendid võivad puududa. Seetõttu on parem kasutada UIAutomationCore.dll otse (kui olete kuulnud UiaComWrapperist C#-is, siis see on see).

COM liideste tüübid:

(1) Põhiline IUknown — "kõikide kurjade juur". Kõige madalama taseme, mitte kunagi kasutajasõbralik.
(2) IDispatch ja selle järglased (näiteks, Excel.Application), mida saab kasutada Pythonis paketi win32com.client abil (kuulub pyWin32-sse). Kõige mugavam ja ilusam variant.
(3) Kohandatud liideste, millega oskab töötada kolmanda osapoole Python pakett comtypes.

Tööriistad: TestStack.White C#-s, pywinauto 0.6.0+, Winium.Desktop C#-s, Python-UIAutomation-for-Windows (nende C-koodiga mähiste allikakood UIAutomationCore.dll ei ole avalik), RAutomation Ruby-s.

AT-SPI

Kuigi peaaegu kõik Linuxi perekonna distrood on ehitatud X Window süsteemi peale (Fedora 25-s on "iksid" asendatud Waylandiga), võimaldavad "iksid" töötada ainult tippakendega ja hiire/kliaviatuuriga. Nuppude, loendikastide ja nii edasi detailsete analüüside jaoks eksisteerib AT-SPI tehnoloogia. Kõige populaarsematel aknahalduritel on nn AT-SPI registry demons, mis tagavad rakendustele automatiseeritava GUI (minimaalselt toetatakse Qt-d ja GTK-d).

Tööriistad: pyatspi2.

pyatspi2 sisaldab minu arvates liiga palju sõltuvusi, nagu PyGObject. Tehnoloogia ise on saadaval tavapärase dünaamilise raamatukoguna. libatspi.so. Sellele pääseb ligi Viidatud käsiraamat. Pywinauto raamatukogu toetuse rakendamiseks plaanime kasutada AT-SPI-d, laadides libatspi.so ja ctypes mooduli. Ainult versiooni kasutamisega on väike probleem, kuna GTK+ ja Qt rakendustele on nad veidi erinevad. Ootame pywinauto 0.7.0 tõenäolist väljaandmist, mis pakub täielikku Linuxi tuge, 2018. aasta esimeses pooles.

Apple Accessibility API

MacOS-il on oma automatiseerimiskeel AppleScript. Kuidas midagi sarnast Pythonis ellu viia, tuleb loomulikult kasutada ObjectiveC funktsioone. Alates MacOS 10.6-st on eelinstalleeritud Pythonis pyobjc pakett. See lihtsustab ka sõltuvuste nimekirja tulevase toega pywinautos.

Tööriistad: lisaks AppleScripti keelele tasub tähelepanu pöörata ATOMac, tuntud ka kui pyatom. See on LDTP-ga liidese poolest ühilduv, kuid on samuti iseseisev raamatukogu. Sellel on näidis iTunesi automatiseerimisest macOS-is, mille koostas minu õpilane. On tuntud probleem: paindlikud ajad (meetodid waitFor*) ei tööta. Aga üldiselt on see üsna kasulik asi.

Kuidas alustada pywinauto kasutamist

Esmalt on hea hakata kasutama GUI objekti inspektorit (tuntud kui Spy tool). See aitab uurida rakendust seestpoolt: kuidas on elementide hierarhia üles ehitatud, millised omadused on saadaval. Kõige tuntumad objekti inspektorid:

  • Spy++ — kuulub Visual Studio komplekti, sealhulgas Express või Community Edition. Kasutab Win32 API-d. Samuti on tuntud selle kloon AutoIt Window Info.
  • Inspect.exe — kuulub Windows SDK-sse. Kui see on teil installitud, siis 64-bitise Windowsi korral leiate selle kaustast C:Program Files (x86)Windows Kitsbinx64. Inspektoris tuleb valida režiim UI Automation asemel MS AA (Active Accessibility, UI Automatsiooni eelkäija).

Rakendust põhjalikult uurides valime tagaplaani, mida kasutame. Piisab tagaplaani nime määramisest rakenduse objekti loomisel.

  • backend=»win32″ — kasutatakse vaikimisi, toimib hästi MFC, WTL, VB6 ja teiste vanade rakendustega.
  • backend=»uia» — uus tagapind MS UI Automation'i jaoks: toimib ideaalselt WPF ja WinFormsiga; töötab hästi ka Delphi ja Windows Store rakendustega; toetab Qt5 ja mõningaid Java rakendusi. Ja üldiselt, kui Inspect.exe näeb elemente ja nende omadusi, siis see tagapind sobib. Üldiselt toetab enamik brausereid ka UI Automation'it (Mozilla vaikimisi, Chrome vajab käivitamisel käsurea võtme). --force-renderer-accessibility, et näha elemente lehtedel Inspect.exe-s). Loomulikult ei ole siin konkurents Seleniumiga tõenäoliselt võimalik. Lihtsalt veel üks viis brauseriga töötamiseks (võib olla kasulik risttoote stsenaariumi jaoks).

Automatiseerimise sisenemispunktid

Rakendust on piisavalt uuritud. On aeg luua Application objekt ja see käivitada või liituda juba käivitatud versiooniga. See ei ole lihtsalt standardklasside kloon subprocess.Popen, vaid sisendi objekt, mis piirab kõiki teie toiminguid protsessi piiridega. See on väga kasulik, kui on käivitatud mitu rakenduse instantsi ja teised ei huvita.

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

# Kirjeldame akent, mille soovime Notepad.exe protsessis leida
dlg_spec = app.UntitledNotepad
# ootame, kuni aken tõeliselt ilmub
actionable_dlg = dlg_spec.wait('visible')

Kui soovite samal ajal hallata mitut rakendust, aitab teid klass Desktop. Näiteks Win10 kalkulaatoris on elementide hierarhia venitatud lausa mitme protsessi vahel (mitte ainult calc.exe). Nii et objekti Desktop ilma ei saa hakkama.

from subprocess import Popen
from pywinauto import Desktop

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

Juurtotse (Application või Desktop) on ainus koht, kus tuleb bäkendi määrata. Kõik muu on läbinähtav ja sobitub „spetsifikatsioon->wrappper“ kontseptsiooniga, millest edasi.

Aken/elemendi spetsifikatsioonid

See on peamine kontseptsioon, millele pywinauto liides põhineb. Saate akent/elementi kirjeldada umbkaudu või detailselt, isegi kui see ei eksisteeri veel või on juba suletud. Aknaspetsifikatsioon (objekt WindowSpecification) säilitab kriteeriumid, mille alusel tuleb otsida tõelist akent või elementi.

Näide akna detailsest spetsifikatsioonist:

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

>>> dlg_spec


>>> dlg_spec.wrapper_object()

Aken otsing toimub meetodi väljakutse kaudu .wrapper_object(). See tagastab teatud "vrapperi" reaalsele aknale/elemendile või tekib ElementNotFoundError (mõnikord ElementAmbiguousError, kui leiti mitu elementi, seega on vajalik otsingukriteeriumite täpsustamine). See "vrapper" oskab juba teha teatud toiminguid elemendiga või saada sealt andmeid.

Python võib varjata väljakutse .wrapper_object(), nii et lõppkood muutub lühemaks. Soovitame seda kasutada ainult silumise jaoks. Järgmised kaks rida teevad absoluutselt sama:

dlg_spec.wrapper_object().minimize() # silumine
dlg_spec.minimize() # tootmine

Akna spetsifikatsioonide otsimiseks on mitmeid kriteeriume. Siin on vaid mõned näited:

# могут иметь несколько уровней
app.window(title_re='.* - Notepad$').window(class_name='Edit')

# можно комбинировать критерии (как AND) и не ограничиваться одним процессом приложения
dlg = Desktop(backend="uia").Calculator
dlg.window(auto_id='num8Button', control_type='Button')

Kõik võimalike kriteeriumide nimekiri on funktsiooni dokumentatsioonis pywinauto.findwindows.find_elements(…).

Atribuutide ja võtmete kaudu juurdepääsu maagia

Python lihtsustab akna spetsifikatsioonide koostamist ja tuvastab objekti atribuudid dünaamiliselt (sisemiselt on üle kirjutatud meetod __getattribute__). Loomulikult kehtivad atribuutide nimedele samasugused piirangud nagu iga muu muutuja nimele (ruume, komasid ja muid erimärke ei saa lisada). Õnneks kasutab pywinauto nii nimetatud „parimat sobivust“ otsingu algoritmi, mis on kirjutamisvigade ja väikeste variatsioonide suhtes vastupidav.

app.UntitledNotepad
# sama mis
app.window(best_match='UntitledNotepad')

Kui siiski on vajalikud Unicode stringid (näiteks vene keeles), ruumid jne, saab juurde pääseda võtme kaudu (nagu tavalise sõnaraamatu puhul):

app['Untitled - Notepad']
# sama mis
app.window(best_match='Untitled - Notepad')

Viis reeglit maagiliste nimede kohta

Kuidas teada saada etaloniliseid maagilisi nimesid? Need, mis määratakse elemendile enne otsimist. Kui olete märkinud nime, mis on piisavalt sarnane etalonile, siis element leitakse.

  1. Pealkirja (tekst, nimi) järgi: app.Properties.OK.click()
  2. Teksti ja elemendi tüübi järgi: app.Properties.OKButton.click()
  3. Tüübi ja numbri järgi: app.Properties.Button3.click() (nimed Button0 ja Button1 on seotud esimese leitud elemendiga, Button2 — teisega ning edasi juba järjestikku — see on ajalooliselt kujunenud)
  4. Staatilise teksti (vasakul või üleval) ja tüübi järgi: app.OpenDialog.FileNameEdit.set_text("") (kasulik dünaamilise tekstiga elementide puhul)
  5. Tüübi ja teksti järgi sees: app.Properties.TabControlSharing.select("General")

Tavaliselt rakendatakse kahte või kolme reeglit korraga, harva rohkem. Konkreetsete nimede kontrollimiseks, mis on saadaval iga elemendi jaoks, saab kasutada meetodit print_control_identifiers(). See suudab printida elementide puu nii ekraanile kui ka faili. Iga elemendi kohta prinditakse välja selle standardne maagiline nimi. Samuti saab sealt kopeerida täiendavat teavet alamelementide kohta. Tulemuseks skriptis on midagi sellist:

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

Elementide puu ise — tavaliselt üsna suur tekst.

>>> app.Properties.print_control_identifiers()

Kontrollidentifikaatorid:

Dialoog - 'Windows NT omadused'    (L688, T518, R1065, B1006)
[u'Windows NT omadusedDialoog', u'Dialoog', u'Windows NT omadused']
child_window(title="Windows NT omadused", control_type="Aken")
   |
   | Pilt - ''    (L717, T589, R749, B622)
   | [u'', u'0', u'Image1', u'Image0', 'Pilt', u'1']
   | child_window(auto_id="13057", control_type="Pilt")
   |
   | Pilt - ''    (L717, T630, R1035, B632)
   | ['Pilt2', u'2']
   | child_window(auto_id="13095", control_type="Pilt")
   |
   | Edit - 'Kausta nimi:'    (L790, T596, R1036, B619)
   | [u'3', 'Edit', u'Edit1', u'Edit0']
   | child_window(title="Kausta nimi:", auto_id="13156", control_type="Edit")
   |
   | Statiiline - 'Tüüp:'    (L717, T643, R780, B658)
   | [u'Tüüp:Statiiline', u'Statiiline', u'Statiiline1', u'Statiiline0', u'Tüüp:']
   | child_window(title="Tüüp:", auto_id="13080", control_type="Tekst")
   |
   | Edit - 'Tüüp:'    (L790, T643, R1036, B666)
   | [u'4', 'Edit2', u'Tüüp:Edit']
   | child_window(title="Tüüp:", auto_id="13059", control_type="Edit")
   |
   | Statiiline - 'Asukoht:'    (L717, T669, R780, B684)
   | [u'Asukoht:Statiiline', u'Asukoht:', u'Statiiline2']
   | child_window(title="Asukoht:", auto_id="13089", control_type="Tekst")
   |
   | Edit - 'Asukoht:'    (L790, T669, R1036, B692)
   | ['Edit3', u'Asukoht:Edit', u'5']
   | child_window(title="Asukoht:", auto_id="13065", control_type="Edit")
   |
   | Statiiline - 'Suurus:'    (L717, T695, R780, B710)
   | [u'Suurus:Statiiline', u'Suurus:', u'Statiiline3']
   | child_window(title="Suurus:", auto_id="13081", control_type="Tekst")
   |
   | Edit - 'Suurus:'    (L790, T695, R1036, B718)
   | ['Edit4', u'6', u'Suurus:Edit']
   | child_window(title="Suurus:", auto_id="13064", control_type="Edit")
   |
   | Statiiline - 'Suurus kettal:'    (L717, T721, R780, B736)
   | [u'Suurus kettal:', u'Suurus kettal:Statiiline', u'Statiiline4']
   | child_window(title="Suurus kettal:", auto_id="13107", control_type="Tekst")
   |
   | Edit - 'Suurus kettal:'    (L790, T721, R1036, B744)
   | ['Edit5', u'7', u'Suurus kettal:Edit']
   | child_window(title="Suurus kettal:", auto_id="13106", control_type="Edit")
   |
   | Statiiline - 'Sisaldab:'    (L717, T747, R780, B762)
   | [u'Sisaldab:1', u'Sisaldab:0', u'Sisaldab:Statiiline', u'Statiiline5', u'Sisaldab:']
   | child_window(title="Sisaldab:", auto_id="13088", control_type="Tekst")
   |
   | Edit - 'Sisaldab:'    (L790, T747, R1036, B770)
   | [u'8', 'Edit6', u'Sisaldab:Edit']
   | child_window(title="Sisaldab:", auto_id="13087", control_type="Edit")
   |
   | Pilt - 'Sisaldab:'    (L717, T773, R1035, B775)
   | [u'Sisaldab:Pilt', 'Pilt3', u'Sisaldab:2']
   | child_window(title="Sisaldab:", auto_id="13096", control_type="Pilt")
   |
   | Statiiline - 'Loodud:'    (L717, T786, R780, B801)
   | [u'Loodud:', u'Loodud:Statiiline', u'Statiiline6', u'Loodud:1', u'Loodud:0']
   | child_window(title="Loodud:", auto_id="13092", control_type="Tekst")
   |
   | Edit - 'Loodud:'    (L790, T786, R1036, B809)
   | [u'Loodud:Edit', 'Edit7', u'9']
   | child_window(title="Loodud:", auto_id="13072", control_type="Edit")
   |
   | Pilt - 'Loodud:'    (L717, T812, R1035, B814)
   | [u'Loodud:Pilt', 'Pilt4', u'Loodud:2']
   | child_window(title="Loodud:", auto_id="13097", control_type="Pilt")
   |
   | Statiiline - 'Atribuudid:'    (L717, T825, R780, B840)
   | [u'Atribuudid:Statiiline', u'Statiiline7', u'Atribuudid:']
   | child_window(title="Atribuudid:", auto_id="13091", control_type="Tekst")
   |
   | Kontrollkasti - 'Ainult lugemisõigus (kehtib ainult kaustas olevate failide kohta)'    (L790, T825, R1035, B841)
   | [u'Kontrollkasta0', u'Kontrollkasta1', 'Kontrollkast', u'Ainult lugemisõigus (kehtib ainult kaustas olevate failide kohta)Kontrollkats', u'Ainult lugemisõigus (kehtib ainult kaustas olevate failide kohta)']
   | child_window(title="Ainult lugemisõigus (kehtib ainult kaustas olevate failide kohta)", auto_id="13075", control_type="Kontrollkaste")
   |
   | Kontrollkasti - 'Peidetud'    (L790, T848, R865, B864)
   | ['Kontrollkasta2', u'PeidetudKontrollkaste', u'Peidetud']
   | child_window(title="Peidetud", auto_id="13076", control_type="Kontrollkaste")
   |
   | Nupp - 'Täiendav...'    (L930, T845, R1035, B868)
   | [u'Täiendav...', u'Täiendav...Nupp', 'Nupp', u'Nupp1', u'Nupp0']
   | child_window(title="Täiendav...", auto_id="13154", control_type="Nupp")
   |
   | Nupp - 'OK'    (L814, T968, R889, B991)
   | ['Nupp2', u'OK', u'OKNupp']
   | child_window(title="OK", auto_id="1", control_type="Nupp")
   |
   | Nupp - 'Tühista'    (L895, T968, R970, B991)
   | ['Nupp3', u'TühistaNupp', u'Tühista']
   | child_window(title="Tühista", auto_id="2", control_type="Nupp")
   |
   | Nupp - 'Rakenda'    (L976, T968, R1051, B991)
   | ['Nupp4', u'RakendaNupp', u'Rakenda']
   | child_window(title="Rakenda", auto_id="12321", control_type="Nupp")
   |
   | Vahekaartide juhtimine - ''    (L702, T556, R1051, B962)
   | [u'10', u'VahekaartideJagamine', u'VahekaartideEelnevad versioonid', u'VahekaartideTurve', u'Vahekaartide', u'VahekaartideKohandamine']
   | child_window(auto_id="12320", control_type="Vahekaart")
   |    |
   |    | Vahekaart - 'Üldine'    (L704, T558, R753, B576)
   |    | [u'ÜldineVahekaart', 'Vahekaart', u'Üldine', u'Vahekaart0', u'Vahekaart1']
   |    | child_window(title="Üldine", control_type="Vahekaart")
   |    |
   |    | Vahekaart - 'Jagamine'    (L753, T558, R801, B576)
   |    | [u'Jagamine', u'JagamineVahekaart', 'Vahekaart2']
   |    | child_window(title="Jagamine", control_type="Vahekaart")
   |    |
   |    | Vahekaart - 'Turve'    (L801, T558, R851, B576)
   |    | [u'Turve', 'Vahekaart3', u'TurveVahekaart']
   |    | child_window(title="Turve", control_type="Vahekaart")
   |    |
   |    | Vahekaart - 'Eelnevad versioonid'    (L851, T558, R947, B576)
   |    | [u'Eelnevad versioonidVahekaart', u'Eelnevad versioonid', 'Vahekaart4']
   |    | child_window(title="Eelnevad versioonid", control_type="Vahekaart")
   |    |
   |    | Vahekaart - 'Kohandamine'    (L947, T558, R1007, B576)
   |    | [u'KohandamineVahekaart', 'Vahekaart5', u'Kohandamine']
   |    | child_window(title="Kohandamine", control_type="Vahekaart")
   |
   | Pealkirja riba - 'Puudub'    (L712, T521, R1057, B549)
   | ['PealkirjaRiba', u'11']
   |    |
   |    | Menüü - 'Süsteem'    (L696, T526, R718, B548)
   |    | [u'Süsteem0', u'Süsteem', u'Süsteem1', u'Menüü', u'SüsteemMenüü']
   |    | child_window(title="Süsteem", auto_id="MenüüRiba", control_type="MenüüRiba")
   |    |    |
   |    |    | Menüüelement - 'Süsteem'    (L696, T526, R718, B548)
   |    |    | [u'Süsteem2', u'Menüüelement', u'SüsteemMenüüElement']
   |    |    | child_window(title="Süsteem", control_type="MenüüElement")
   |    |
   |    | Nupp - 'Sulge'    (L1024, T519, R1058, B549)
   |    | [u'SulgeNupp', u'Sulge', 'Nupp5']
   |    | child_window(title="Sulge", control_type="Nupp")

Mõnel juhul võib kogu puu printimine olla nõrk (näiteks iTunesis, kus ühel vahelehel on lausa kolm tuhat elementi!), kuid saab kasutada parameetrit depth (sügavus): depth=1 — ise element, depth=2 — ainult otsesed lapsed ja nii edasi. Seda saab samuti määrata spetsiifikates, kui luua child_window.

Näited

Me pidevalt täiendame näidiste nimekirja hoidlas. Uutest tasub märkida WireSharki võrguanalüsaatori automatiseerimise (see on hea näide Qt5 rakendusest; kuigi seda ülesannet saab lahendada ka ilma GUI-ta, on ju olemas scapy.Sniffer Pythoniga pakett scapy). Samuti on olemas MS Painti automatiseerimise näide koos tema ribamenüüga.

Veel üks suurepärane näide, mille on kirjutanud mu tudeng: faili lohistamine explorer.exe-st Chrome'i lehele Google Drive'i jaoks (see liigutatakse peamisse hoidlasse veidi hiljem).

Ja muidugi, klaviatuurisündmuste (kuumad nõtked) ja hiire sündmuste jälgimise näide:
hook_and_listen.py.

Tänud

Eriline tänu — neile, kes pidevalt aitavad projekti arendada. Minule ja Valentinile on see pidev hobi. Kaks mu tudengit NNGU-st kaitsesid hiljuti sellel teemal bakalaureusekraadi. Aleksandr on suurendanud tuge MS UI Automationi toetuseks ja alustanud automaatse koodigeneraatori loomist põhimõttel 'salvestamine-mängimine' tekstipõhiste omaduste põhjal (see on kõige keerulisem funktsioon), praegu ainult 'uia' tagaplaanile. Ivan arendab uut Linuxi tagaplaani AT-SPI põhjal (moodulid hiire ja klaviatuur põhjal python-xlib — juba versioonides 0.6.x).

Kuna olen juba mõnda aega õppinud automatiseerimise erikursust Pythonis, teevad osa magistriõppe üliõpilastest kodutöid, rakendades väikeseid funktsioone või automatiseerimise näiteid. Mõningaid olulisi asju avastasid samuti üliõpilased uurimisfaasis. Kuigi mõnikord peab koodi kvaliteeti rangelt jälgima. Sellega aitavad palju staatilised analüsaatorid (QuantifiedCode, Codacy ja Landscape) ja automaatsed testid pilves (AppVeyor teenus) ning koodi katteprotsent on umbes 95%.

Samuti aitäh kõigile, kes jätavad tagasisidet, avavad vigu ja saadavad pulli päringuid!

Lisavahendid

Küsimuste jälgimise jaoks jälgime märgistust StackOverflow'is (hiljuti ilmus märk vene SO versioonis) ja võtmesõna Toosteris. On vene keeles Gitteri vestluses.

Iga kuu värskendame open-source GUI testimise raamatukogude reitingut. GitHubis on kiiremini kasvavad ainult Autohotkey (neil on väga suur kogukond ja pikk ajalugu) ja PyAutoGUI (suur osa sellest on tingitud tema autori Al Sweigarti raamatute populaarsusest: „Automate the Boring Stuff with Python” ja muud).

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster