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(). Няколко условия се комбинират автоматично чрез логическо И.
| Метод на 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 и стандартния тестов runner 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също