UI Automator је фрејмворк од Google-а за аутоматизовано UI тестирање Android апликација, који ради на нивоу система и може да интерагује са елементима интерфејса изван једне апликације. За разлику од Espresso-а, UI Automator није везан за процес одређене апликације: може да отвара системске дијалоге, панел обавештења и да се пребацује између апликација. Према Google Android Developers, UI Automator користи стандардни Accessibility Service за приступ UI стаблу уређаја.
Главне ствари
UI Automator је фрејмворк за функционално UI тестирање Android-а који ради на нивоу оперативног система. Он пружа API за приступ било ком елементу на екрану уређаја, без обзира на то којој апликацији припада — укључујући системску статусну траку, дијалоге за дозволе, почетни екран и апликације трећих страна. То га чини незаменљивим за тестирање сценарија који излазе из оквира једне апликације.
Архитектонски, UI Automator користи Accessibility Service — исти сервис који користе TalkBack, Switch Access и други алати за приступачност. Кроз овај сервис, фрејмворк добија потпуно стабло UI компоненти тренутног екрана и омогућава извођење радњи над њима: клик, превлачење, унос текста, дуги притисак.
UI Automator се први пут појавио у Android 4.3 (API 18) и од тада је део Android Testing Support Library као званични Google-ов алат за међуапликацијско тестирање. У AndroidX Test-у је доступан као засебан артефакт androidx.test.uiautomator:uiautomator верзије 2.3.0 (2024), који подржава све верзије Android-а од API 18.
Принцип рада UI Automator-а се заснива на скенирању Accessibility стабла тренутног екрана. При позиву методе findObject(selector), фрејмворк пролази кроз хијерархију View-а, проналази први елемент који задовољава услове UiSelector-а и враћа објекат UiObject — прокси за интеракцију са правим View-ом.
Типичан UI Automator тест почиње добијањем инстанце UiDevice, која представља физички уређај. UiDevice пружа методе за претрагу елемената, управљање притисцима дугмади (Home, Back, Recent), ротацију екрана и снимке екрана. Након проналажења елемента кроз UiSelector, извршавају се радње над UiObject-ом.
У примеру испод, тест отвара апликацију Settings, проналази ставку „Батерија” по тексту и кликће на њу. UI Automator не захтева покретање Activity — ради са било којим екраном уређаја, укључујући апликације трећих страна.
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Отвори екран подешавања
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("Подешавања")), 2000)
// Пронађи ставку „Батерија” и притисни
val batteryItem = device.findObject(
UiSelector().text("Батерија")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)
UiDevice — главна класа за интеракцију са уређајем. Пружа методе за претрагу елемената, симулацију притиска хардверских дугмади (Home, Back, Menu, Volume), управљање напајањем, снимке екрана и чекање одређених стања екрана. UiDevice се креира једном по тесту и поново користи за све операције.
UiSelector — fluent API за претрагу UI елемената. За разлику од ViewMatchers-а из Espresso-а, UiSelector не захтева компајлирање — услови претраге се формирају кроз ланац метода: text(), className(), description(), resourceId(), index(). Више услова се аутоматски комбинује кроз логичко AND.
| Метода UiSelector-а | Намена |
|---|---|
| text(String) | Претрага по тачном тексту елемента |
| textContains(String) | Претрага по делу текста |
| resourceId(String) | Претрага по ID ресурса (нпр. com.example:id/button) |
| className(String) | Претрага по имену класе View-а |
| description(String) | Претрага по content-description |
| childSelector(selector) | Претрага подређеног елемента у контејнеру |
Када на екрану постоји више елемената са истим текстом, UiSelector омогућава комбиновање критеријума: проналажење контејнера по ID-у, затим унутар њега — елемента по тексту и класи. Ово гарантује јединствену идентификацију потребне компоненте. Метода childSelector сужава подручје претраге на наведени контејнер, што убрзава навигацију кроз UI стабло.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// Унутар листе пронађи елемент са текстом „Wi-Fi”
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
Cross-application (међуапликацијско) тестирање — главна функција због које се бира UI Automator. Фрејмворк може да се пребацује између апликација, тестира OAuth пријаву преко прегледача, проверава системске дијалоге (дозволе, избор апликације) и интерагује са системском статусном траком, панелом обавештења и закључаним екраном.
Типичан сценариј cross-app теста: апликација отвара прегледач за OAuth ауторизацију, корисник уноси корисничко име и лозинку, прегледач преусмерава назад у апликацију. UI Automator се пребацује између процеса, проналази поља за унос у прегледачу, попуњава их и кликће на „Пријава”.
// Чекање појављивања прегледача
device.wait(Until.hasObject(
UiSelector().packageName("com.android.chrome")
), 5000)
// Претрага поља за унос е-поште у прегледачу
val emailField = device.findObject(
UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"
UI Automator може да проверава и затвара системске дијалоге — дозволе за геолокацију, обавештења, приступ датотекама. Ово је критично за тестирање првог покретања апликације, када систем узастопно тражи неколико дозвола. Без UI Automator-а, такви сценарији се не могу аутоматизовати јер системски дијалози не припадају процесу апликације.
Избор између UI Automator-а и Espresso-а зависи од сценарија тестирања. Espresso је оптимизован за тестирање једне апликације са аутоматском синхронизацијом и минималним boilerplate-ом. UI Automator је погодан за сценарије где је потребна интеракција са системом, прегледачем или више апликација.
| Критеријум | UI Automator | Espresso |
|---|---|---|
| Област | Цео уређај, више апликација | Једна апликација |
| Синхронизација | Ручна (wait, sleep) | Аутоматска (Idling Resource) |
| Брзина | Спорије (приступ кроз сервис) | Брже (ради унутар процеса) |
| System UI | Подржава (Notifications, Quick Settings) | Не подржава |
| Прецизност претраге | UiSelector по атрибутима | ViewMatchers по типу и хијерархији |
| Стабилност | Нижа (зависи од тајминга) | Виша (аутоматско чекање) |
У пракси, ови фрејмворци се често користе заједно: Espresso покрива UI тестове главне апликације са високом стабилношћу, а UI Automator се прикључује за сценарије који излазе из граница апликације — OAuth пријава, системске дозволе, рад са Share Intent-ом. Таква комбинација даје максимално UI покриће уз минималне трошкове одржавања тестова.
Повезивање UI Automator-а се врши додавањем зависности у build.gradle. Фрејмворк је део AndroidX Test-а и не захтева додатне дозволе у манифесту — приступ Accessibility Service-у се подешава аутоматски при покретању инструменталног теста.
Минимална конфигурација укључује артефакт uiautomator и стандардни тест раннер AndroidJUnitRunner. UI Automator тестови се смештају у директоријум src/androidTest и покрећу на емулатору или физичком уређају са 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")
}
За добијање инстанце UiDevice-а користи се InstrumentationRegistry.getInstrumentation(). UiDevice треба креирати једном у методи setUp() и поново користити у свим тестовима класе ради уштеде ресурса уређаја. Важно је напоменути да UiDevice није thread-safe — све операције морају да се извршавају у једној нити тест методе. Креирање новог UiDevice-а у сваком тесту доводи до додатног оптерећења и успоравања извршења. Препоручује се креирање UiDevice-а једном у методи beforeClass и поновно коришћење за све тестове тестне класе.
За разлику од Espresso-а, UI Automator нема аутоматску синхронизацију. За чекање појављивања елемената користи се метода UiDevice.wait(condition, timeout) са објектом Until: Until.findObject(selector), Until.hasObject(selector), Until.gone(selector). Без исправног чекања, тестови постају нестабилни због race condition-а — елемент можда неће стићи да се појави на екрану до тренутка претраге. Препоручује се постављање тајмаута од најмање 3-5 секунди за стабилност.
Често постављана питања
UI Automator ради на нивоу Accessibility Service-а и може да интерагује са било којим апликацијама. Espresso ради унутар процеса једне апликације и користи аутоматску синхронизацију са UI нити. UI Automator је бољи за међуапликацијске сценарије, Espresso — за стабилне тестове једне апликације.
Да, UI Automator ради на свим уређајима са Android API 18+. Не захтева root приступ — користи се стандардни Accessibility Service који се активира кроз Instrumentation при покретању тестова.
UI Automator користи Accessibility Service за добијање потпуног стабла UI компоненти тренутног екрана. Затим UiSelector пролази кроз ово стабло и проналази елементе по задатим критеријумима: текст, класа, ID, content-description или њихова комбинација.
Да, метода UiDevice.takeScreenshot(storePath) омогућава снимање тренутног екрана и чување у датотеку. Ово је корисно за отклањање грешака: при паду теста може се сачувати снимак екрана и анализирати стање екрана.
UI Automator нема аутоматску синхронизацију, па су тестови осетљиви на тајминг. Ако анимација није завршена или View није стигао да се рендерује, findObject можда неће пронаћи елемент. Решење — коришћење UiDevice.wait() са довољним тајмаутом.
Закључак
Комплет алата UI Automator-а покрива све кључне сценарије међуапликацијског тестирања и представља стандард за Android аутоматизацију на нивоу система.
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође