Ang UI Automator ay isang framework mula sa Google para sa automated na UI testing ng Android applications, na gumagana sa antas ng system at maaaring makipag-ugnayan sa mga elemento ng interface sa labas ng isang application. Hindi tulad ng Espresso, ang UI Automator ay hindi nakatali sa proseso ng isang partikular na application: maaari itong magbukas ng mga system dialog, Notification panel, at lumipat sa pagitan ng mga application. Ayon sa Google Android Developers, ang UI Automator ay gumagamit ng standard na Accessibility Service para ma-access ang UI tree ng device.
Mga Pangunahing Punto
UI Automator ay isang framework para sa functional na UI testing ng Android na gumagana sa antas ng operating system. Nagbibigay ito ng API para ma-access ang anumang elemento sa screen ng device, kahit saang application ito kabilang — kabilang ang system status bar, permission dialogs, home screen, at third-party na applications. Ginagawa nitong kailangang-kailangan para sa pagsubok ng mga scenario na lampas sa isang application.
Sa arkitektura, ang UI Automator ay gumagamit ng Accessibility Service — ang parehong serbisyo na ginagamit ng TalkBack, Switch Access, at iba pang accessibility tools. Sa pamamagitan ng serbisyong ito, nakukuha ng framework ang kumpletong UI component tree ng kasalukuyang screen at pinapayagan ang pag-execute ng mga aksyon sa mga ito: pag-click, pag-swipe, pag-input ng text, mahabang pagpindot.
Unang lumitaw ang UI Automator sa Android 4.3 (API 18) at mula noon ay bahagi na ito ng Android Testing Support Library bilang opisyal na tool ng Google para sa cross-application testing. Sa AndroidX Test, available ito bilang hiwalay na artifact na androidx.test.uiautomator:uiautomator bersyon 2.3.0 (2024), na sumusuporta sa lahat ng bersyon ng Android mula API 18.
Prinsipyo ng paggana ng UI Automator ay batay sa pag-scan ng Accessibility tree ng kasalukuyang screen. Kapag tinawag ang method na findObject(selector), tinatahak ng framework ang View hierarchy, hinahanap ang unang elemento na tumutugma sa mga kondisyon ng UiSelector, at nagbabalik ng UiObject object — isang proxy para sa pakikipag-ugnayan sa totoong View.
Karaniwang nagsisimula ang UI Automator test sa pagkuha ng instance ng UiDevice, na kumakatawan sa pisikal na device. Nagbibigay ang UiDevice ng mga method para sa paghahanap ng elemento, pamamahala ng pagpindot ng button (Home, Back, Recent), pag-ikot ng screen, at pagkuha ng screenshot. Pagkatapos mahanap ang elemento sa pamamagitan ng UiSelector, isinasagawa ang mga aksyon sa UiObject.
Sa halimbawa sa ibaba, binuksan ng test ang Settings application, hinanap ang item na “Baterya” sa pamamagitan ng text, at pinindot ito. Hindi nangangailangan ang UI Automator ng pag-start ng Activity — gumagana ito sa anumang screen ng device, kabilang ang third-party applications.
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Buksan ang screen ng mga setting
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("Mga Setting")), 2000)
// Hanapin ang item na “Baterya” at pindutin
val batteryItem = device.findObject(
UiSelector().text("Baterya")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)
UiDevice — pangunahing klase para sa pakikipag-ugnayan sa device. Nagbibigay ito ng mga method para sa paghahanap ng elemento, pag-simulate ng pagpindot ng hardware buttons (Home, Back, Menu, Volume), pamamahala ng power, pagkuha ng screenshot, at paghihintay ng partikular na estado ng screen. Ang UiDevice ay ginagawa nang isang beses bawat test at ginagamit muli para sa lahat ng operasyon.
UiSelector — ay isang fluent API para sa paghahanap ng UI elements. Hindi tulad ng ViewMatchers sa Espresso, ang UiSelector ay hindi nangangailangan ng compilation — ang mga kondisyon ng paghahanap ay nabubuo sa pamamagitan ng chain ng mga method: text(), className(), description(), resourceId(), index(). Maraming kondisyon ang awtomatikong pinagsasama sa pamamagitan ng logical AND.
| UiSelector Method | Layunin |
|---|---|
| text(String) | Paghahanap ayon sa eksaktong text ng elemento |
| textContains(String) | Paghahanap ayon sa bahagi ng text |
| resourceId(String) | Paghahanap ayon sa resource ID (hal. com.example:id/button) |
| className(String) | Paghahanap ayon sa pangalan ng klase ng View |
| description(String) | Paghahanap ayon sa content-description |
| childSelector(selector) | Paghahanap ng child element sa loob ng container |
Kapag may maraming elemento na may parehong text sa screen, pinapayagan ng UiSelector ang pagsasama-sama ng criteria: hanapin ang container ayon sa ID, pagkatapos sa loob nito — ang elemento ayon sa text at class. Tinitiyak nito ang natatanging pagkakakilanlan ng kinakailangang component. Ang method na childSelector ay nagpapaliit sa lugar ng paghahanap sa tinukoy na container, na nagpapabilis ng navigation sa UI tree.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// Sa loob ng listahan, hanapin ang elemento na may text na “Wi-Fi”
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
Cross-application (inter-application) na pagsubok — ang pangunahing function kung bakit pinipili ang UI Automator. Ang framework ay maaaring lumipat sa pagitan ng mga application, mag-test ng OAuth login sa pamamagitan ng browser, suriin ang mga system dialog (permissions, application selection), at makipag-ugnayan sa system status bar, notification panel, at lock screen.
Karaniwang scenario ng cross-app test: binuksan ng application ang browser para sa OAuth authorization, nag-input ang user ng username at password, at nag-redirect ang browser pabalik sa application. Ang UI Automator ay lumilipat sa pagitan ng mga proseso, hinahanap ang input fields sa browser, pinupunan ang mga ito, at pinipindot ang “Mag-sign In”.
// Naghihintay sa paglitaw ng browser
device.wait(Until.hasObject(
UiSelector().packageName("com.android.chrome")
), 5000)
// Hanapin ang email input field sa browser
val emailField = device.findObject(
UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"
Ang UI Automator ay maaaring sumuri at magsara ng system dialogs — geolocation permissions, notifications, access sa files. Ito ay kritikal para sa pagsubok ng unang paglunsad ng application, kapag sunod-sunod na humihingi ang system ng maraming permissions. Kung wala ang UI Automator, hindi maaaring i-automate ang mga ganitong scenario dahil ang system dialogs ay hindi pag-aari ng proseso ng application.
Ang pagpili sa pagitan ng UI Automator at Espresso ay nakadepende sa testing scenario. Ang Espresso ay na-optimize para sa pagsubok ng isang application na may automatic synchronization at minimal na boilerplate. Ang UI Automator ay angkop para sa mga scenario na nangangailangan ng interaksyon sa system, browser, o maraming application.
| Kriterya | UI Automator | Espresso |
|---|---|---|
| Saklaw | Buong device, maraming application | Isang application |
| Synchronization | Manual (wait, sleep) | Awtomatiko (Idling Resource) |
| Bilis | Mas mabagal (access sa pamamagitan ng serbisyo) | Mas mabilis (gumagana sa loob ng proseso) |
| System UI | Sinusuportahan (Notifications, Quick Settings) | Hindi sinusuportahan |
| Katumpakan ng Paghahanap | UiSelector ayon sa attributes | ViewMatchers ayon sa uri at hierarchy |
| Katatagan | Mas mababa (depende sa timing) | Mas mataas (awtomatikong paghihintay) |
Sa praktika, ang mga framework na ito ay madalas na ginagamit nang magkasama: Sinasaklaw ng Espresso ang UI tests ng pangunahing application na may mataas na katatagan, at ang UI Automator ay ginagamit para sa mga scenario na lampas sa hangganan ng application — OAuth login, system permissions, paggawa gamit ang Share Intent. Ang kombinasyong ito ay nagbibigay ng maximum na UI coverage na may minimal na gastos sa pagpapanatili ng tests.
Pagkonekta ng UI Automator ay ginagawa sa pamamagitan ng pagdagdag ng dependency sa build.gradle. Ang framework ay bahagi ng AndroidX Test at hindi nangangailangan ng karagdagang permissions sa manifest — ang access sa Accessibility Service ay awtomatikong na-configure kapag nagsimula ang instrumental test.
Ang minimal na configuration ay kinabibilangan ng artifact na uiautomator at standard na test runner na AndroidJUnitRunner. Ang UI Automator tests ay inilalagay sa directory na src/androidTest at pinapatakbo sa emulator o pisikal na device na may 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")
}
Para makuha ang instance ng UiDevice, ginagamit ang InstrumentationRegistry.getInstrumentation(). Ang UiDevice ay dapat gawin nang isang beses sa setUp() method at gamitin muli sa lahat ng tests ng klase upang makatipid ng resources ng device. Mahalagang tandaan na ang UiDevice ay hindi thread-safe — lahat ng operasyon ay dapat isagawa sa isang thread ng test method. Ang paggawa ng bagong UiDevice sa bawat test ay nagdudulot ng overhead at pagbagal ng execution. Inirerekomenda na gawin ang UiDevice nang isang beses sa beforeClass method at gamitin muli para sa lahat ng tests ng test class.
Hindi tulad ng Espresso, ang UI Automator ay walang automatic synchronization. Para sa paghihintay ng paglitaw ng mga elemento, ginagamit ang method na UiDevice.wait(condition, timeout) kasama ang object na Until: Until.findObject(selector), Until.hasObject(selector), Until.gone(selector). Kung walang tamang paghihintay, ang tests ay nagiging hindi stable dahil sa race condition — ang elemento ay maaaring hindi lumitaw sa screen sa oras ng paghahanap. Inirerekomenda na magtakda ng timeout na hindi bababa sa 3-5 segundo para sa katatagan.
Mga Madalas Itanong
UI Automator ay gumagana sa antas ng Accessibility Service at maaaring makipag-ugnayan sa anumang application. Ang Espresso ay gumagana sa loob ng proseso ng isang application at gumagamit ng automatic synchronization sa UI thread. Ang UI Automator ay mas mahusay para sa inter-application scenarios, ang Espresso — para sa stable na tests ng isang application.
Oo, gumagana ang UI Automator sa lahat ng device na may Android API 18+. Hindi ito nangangailangan ng root access — ginagamit ang standard na Accessibility Service, na na-activate sa pamamagitan ng Instrumentation kapag nagsimula ang tests.
Gumagamit ang UI Automator ng Accessibility Service para makuha ang kumpletong UI component tree ng kasalukuyang screen. Pagkatapos, tinatahak ng UiSelector ang tree na ito at hinahanap ang mga elemento ayon sa ibinigay na criteria: text, class, ID, content-description, o kombinasyon ng mga ito.
Oo, ang method na UiDevice.takeScreenshot(storePath) ay nagbibigay-daan sa pagkuha ng screenshot ng kasalukuyang screen at pag-save nito sa isang file. Ito ay kapaki-pakinabang para sa debugging: kapag bumagsak ang test, maaaring i-save ang screenshot at suriin ang estado ng screen.
Ang UI Automator ay walang automatic synchronization, kaya ang tests ay sensitibo sa timing. Kung hindi natapos ang animation o hindi nag-render ang View sa oras, maaaring hindi mahanap ng findObject ang elemento. Solusyon — gamitin ang UiDevice.wait() na may sapat na timeout.
Buod
Sinasaklaw ng set ng mga tool ng UI Automator ang lahat ng pangunahing scenario ng inter-application testing at ito ang standard para sa Android automation sa antas ng system.
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din