UI Automator este un framework de la Google pentru testarea automatizată UI a aplicațiilor Android, care funcționează la nivel de sistem și poate interacționa cu elemente de interfață dincolo de o singură aplicație. Spre deosebire de Espresso, UI Automator nu este legat de procesul unei anumite aplicații: poate deschide dialoguri de sistem, panoul de notificări și poate comuta între aplicații. Potrivit Google Android Developers, UI Automator folosește Accessibility Service standard pentru accesarea arborelui UI al dispozitivului.
Principalele puncte
UI Automator este un framework pentru testarea funcțională UI Android, care funcționează la nivel de sistem de operare. Oferă API pentru accesarea oricărui element de pe ecranul dispozitivului, indiferent de aplicația căreia îi aparține — inclusiv bara de stare a sistemului, dialogurile de permisiuni, ecranul principal și aplicațiile terțe. Acest lucru îl face indispensabil pentru testarea scenariilor care depășesc limitele unei singure aplicații.
Din punct de vedere arhitectural, UI Automator folosește Accessibility Service — același serviciu utilizat de TalkBack, Switch Access și alte instrumente de accesibilitate. Prin acest serviciu, framework-ul obține arborele complet al componentelor UI ale ecranului curent și permite executarea acțiunilor asupra lor: clic, glisare, introducere text, apăsare lungă.
UI Automator a apărut pentru prima dată în Android 4.3 (API 18) și de atunci face parte din Android Testing Support Library ca instrument oficial Google pentru testarea cross-aplicații. În AndroidX Test este disponibil ca artefact separat androidx.test.uiautomator:uiautomator versiunea 2.3.0 (2024), care suportă toate versiunile Android de la API 18.
Principiul de funcționare UI Automator se bazează pe scanarea arborelui Accessibility al ecranului curent. La apelarea metodei findObject(selector), framework-ul parcurge ierarhia View, găsește primul element care îndeplinește condițiile UiSelector și returnează un obiect UiObject — un proxy pentru interacțiunea cu View-ul real.
Un test tipic UI Automator începe cu obținerea unei instanțe UiDevice, care reprezintă dispozitivul fizic. UiDevice oferă metode pentru căutarea elementelor, gestionarea apăsărilor de butoane (Home, Back, Recent), rotirea ecranului și capturi de ecran. După găsirea elementului prin UiSelector, se execută acțiuni asupra UiObject.
În exemplul de mai jos, testul deschide aplicația Settings, găsește elementul „Baterie” după text și face clic pe el. UI Automator nu necesită pornirea unei Activity — funcționează cu orice ecran al dispozitivului, inclusiv aplicații terțe.
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Deschide ecranul de setări
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("Setări")), 2000)
// Găsește elementul „Baterie” și apasă
val batteryItem = device.findObject(
UiSelector().text("Baterie")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)
UiDevice — clasa principală pentru interacțiunea cu dispozitivul. Oferă metode pentru căutarea elementelor, simularea apăsării butoanelor hardware (Home, Back, Menu, Volume), gestionarea alimentării, capturi de ecran și așteptarea unor stări specifice ale ecranului. UiDevice se creează o dată per test și se reutilizează pentru toate operațiile.
UiSelector — este o API fluent pentru căutarea elementelor UI. Spre deosebire de ViewMatchers din Espresso, UiSelector nu necesită compilare — condițiile de căutare se formează printr-un lanț de metode: text(), className(), description(), resourceId(), index(). Mai multe condiții sunt combinate automat prin AND logic.
| Metoda UiSelector | Destinație |
|---|---|
| text(String) | Căutare după textul exact al elementului |
| textContains(String) | Căutare după o parte din text |
| resourceId(String) | Căutare după ID-ul resursei (de ex. com.example:id/button) |
| className(String) | Căutare după numele clasei View |
| description(String) | Căutare după content-description |
| childSelector(selector) | Căutarea unui element copil într-un container |
Când pe ecran există mai multe elemente cu același text, UiSelector permite combinarea criteriilor: găsirea containerului după ID, apoi în interiorul acestuia — elementul după text și clasă. Aceasta garantează identificarea unică a componentei necesare. Metoda childSelector restrânge aria de căutare la containerul specificat, accelerând navigarea prin arborele UI.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// În interiorul listei găsește elementul cu textul „Wi-Fi”
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
Cross-application (testarea între aplicații) — principala funcție pentru care se alege UI Automator. Framework-ul poate comuta între aplicații, testa autentificarea OAuth prin browser, verifica dialogurile de sistem (permisiuni, selectarea aplicației) și interacționa cu bara de stare a sistemului, panoul de notificări și ecranul de blocare.
Un scenariu tipic de test cross-app: aplicația deschide browserul pentru autorizare OAuth, utilizatorul introduce numele de utilizator și parola, browserul redirecționează înapoi în aplicație. UI Automator comută între procese, găsește câmpurile de introducere în browser, le completează și face clic pe „Autentificare”.
// Așteptarea apariției browserului
device.wait(Until.hasObject(
UiSelector().packageName("com.android.chrome")
), 5000)
// Căutarea câmpului de introducere email în browser
val emailField = device.findObject(
UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"
UI Automator poate verifica și închide dialogurile de sistem — permisiuni de geolocație, notificări, acces la fișiere. Acest lucru este esențial pentru testarea primei lansări a aplicației, când sistemul solicită succesiv mai multe permisiuni. Fără UI Automator, astfel de scenarii nu pot fi automatizate, deoarece dialogurile de sistem nu aparțin procesului aplicației.
Alegerea între UI Automator și Espresso depinde de scenariul de testare. Espresso este optimizat pentru testarea unei singure aplicații cu sincronizare automată și boilerplate minim. UI Automator este potrivit pentru scenarii care necesită interacțiune cu sistemul, browserul sau mai multe aplicații.
| Criteriu | UI Automator | Espresso |
|---|---|---|
| Domeniu | Întreg dispozitivul, mai multe aplicații | O singură aplicație |
| Sincronizare | Manuală (wait, sleep) | Automată (Idling Resource) |
| Viteză | Mai lent (acces prin serviciu) | Mai rapid (funcționează în proces) |
| System UI | Suportă (Notifications, Quick Settings) | Nu suportă |
| Precizia căutării | UiSelector după atribute | ViewMatchers după tip și ierarhie |
| Stabilitate | Mai scăzută (depinde de sincronizare) | Mai ridicată (așteptare automată) |
În practică, aceste framework-uri sunt adesea folosite împreună: Espresso acoperă testele UI ale aplicației principale cu stabilitate ridicată, iar UI Automator este utilizat pentru scenarii care depășesc limitele aplicației — autentificare OAuth, permisiuni de sistem, lucrul cu Share Intent. Această combinație oferă o acoperire maximă UI cu costuri minime de întreținere a testelor.
Conectarea UI Automator se face prin adăugarea dependenței în build.gradle. Framework-ul face parte din AndroidX Test și nu necesită permisiuni suplimentare în manifest — accesul la Accessibility Service se configurează automat la pornirea testului instrumental.
Configurația minimă include artefactul uiautomator și runner-ul standard de test AndroidJUnitRunner. Testele UI Automator se plasează în directorul src/androidTest și se rulează pe emulator sau dispozitiv fizic cu Android API 18+.
dependencies {
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test:runner:1.6.1")
}
Pentru obținerea instanței UiDevice se folosește InstrumentationRegistry.getInstrumentation(). UiDevice trebuie creat o dată în metoda setUp() și reutilizat în toate testele clasei pentru economisirea resurselor dispozitivului. Este important de reținut că UiDevice nu este thread-safe — toate operațiile trebuie executate într-un singur fir al metodei de test. Crearea unui nou UiDevice în fiecare test duce la suprasarcină și încetinirea execuției. Se recomandă crearea UiDevice o dată în metoda beforeClass și reutilizarea lui pentru toate testele clasei de test.
Spre deosebire de Espresso, UI Automator nu are sincronizare automată. Pentru așteptarea apariției elementelor se folosește metoda UiDevice.wait(condition, timeout) cu obiectul Until: Until.findObject(selector), Until.hasObject(selector), Until.gone(selector). Fără așteptări corecte, testele devin instabile din cauza race condition — elementul poate să nu apară pe ecran până la momentul căutării. Se recomandă setarea unui timeout de cel puțin 3-5 secunde pentru stabilitate.
Întrebări frecvente
UI Automator funcționează la nivelul Accessibility Service și poate interacționa cu orice aplicații. Espresso funcționează în interiorul procesului unei singure aplicații și folosește sincronizarea automată cu firul UI. UI Automator este mai bun pentru scenarii inter-aplicații, Espresso — pentru teste stabile ale unei singure aplicații.
Da, UI Automator funcționează pe toate dispozitivele cu Android API 18+. Nu necesită acces root — se folosește Accessibility Service standard, care este activat prin Instrumentation la pornirea testelor.
UI Automator folosește Accessibility Service pentru a obține arborele complet al componentelor UI ale ecranului curent. Apoi UiSelector parcurge acest arbore și găsește elementele după criteriile date: text, clasă, ID, content-description sau combinația lor.
Da, metoda UiDevice.takeScreenshot(storePath) permite realizarea unei capturi a ecranului curent și salvarea ei într-un fișier. Acest lucru este util pentru depanare: la căderea testului, se poate salva captura și analiza starea ecranului.
UI Automator nu are sincronizare automată, de aceea testele sunt sensibile la sincronizare. Dacă animația nu s-a încheiat sau View-ul nu a apucat să se redeze, findObject poate să nu găsească elementul. Soluția — utilizarea UiDevice.wait() cu un timeout suficient.
Concluzii
Setul de instrumente UI Automator acoperă toate scenariile cheie de testare inter-aplicații și este standardul pentru automatizarea Android la nivel de sistem.
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și