UI Automator, Google tarafından Android uygulamalarının otomatik UI testi için oluşturulmuş, sistem düzeyinde çalışan ve tek bir uygulamanın ötesinde arayüz öğeleriyle etkileşime girebilen bir framework'tür. Espresso'nun aksine, UI Automator belirli bir uygulamanın sürecine bağlı değildir: sistem diyaloglarını, bildirim çubuğunu açabilir ve uygulamalar arasında geçiş yapabilir. Google Android Developers'a göre, UI Automator cihazın UI ağacına erişmek için standart Accessibility Service'i kullanır.
Anahtar Noktalar
UI Automator, işletim sistemi düzeyinde çalışan Android işlevsel UI testi için bir framework'tür. Cihaz ekranındaki herhangi bir öğeye, hangi uygulamaya ait olduğuna bakılmaksızın erişmek için API sağlar — sistem durum çubuğu, izin diyalogları, ana ekran ve üçüncü taraf uygulamalar dahil. Bu, onu tek bir uygulamanın ötesine geçen senaryoları test etmek için vazgeçilmez kılar.
Mimari olarak, UI Automator Accessibility Service'i kullanır — TalkBack, Switch Access ve diğer erişilebilirlik araçları tarafından kullanılan aynı hizmet. Bu hizmet aracılığıyla framework, mevcut ekranın tam UI bileşen ağacını alır ve üzerinde işlemler yapılmasına olanak tanır: dokunma, kaydırma, metin girişi ve uzun basma.
UI Automator ilk olarak Android 4.3'te (API 18) ortaya çıktı ve o zamandan beri uygulamalar arası test için Google'ın resmi aracı olarak Android Testing Support Library'nin bir parçasıdır. AndroidX Test'te, API 18'den itibaren tüm Android sürümlerini destekleyen ayrı bir yapıt olarak androidx.test.uiautomator:uiautomator sürüm 2.3.0 (2024) ile kullanılabilir.
Çalışma prensibi: UI Automator, mevcut ekranın erişilebilirlik ağacını taramaya dayanır. findObject(selector) yöntemi çağrıldığında, framework View hiyerarşisini geçer, UiSelector koşullarıyla eşleşen ilk öğeyi bulur ve bir UiObject — gerçek View ile etkileşim için bir proxy döndürür.
Tipik bir UI Automator testi, fiziksel cihazı temsil eden bir UiDevice örneği alarak başlar. UiDevice, öğeleri bulma, düğme basmalarını (Ana Sayfa, Geri, Son) yönetme, ekranı döndürme ve ekran görüntüsü alma yöntemleri sağlar. UiSelector aracılığıyla bir öğe bulunduktan sonra, UiObject üzerinde işlemler gerçekleştirilir.
Aşağıdaki örnekte, test Ayarlar uygulamasını açar, metinle “Pil” öğesini bulur ve ona dokunur. UI Automator bir Activity başlatmayı gerektirmez — üçüncü taraf uygulamalar dahil cihazdaki herhangi bir ekranla çalışır.
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Ayarlar ekranını aç
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("Ayarlar")), 2000)
// "Pil" öğesini bul ve dokun
val batteryItem = device.findObject(
UiSelector().text("Pil")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)
UiDevice, cihazla etkileşim için ana sınıftır. Öğeleri bulma, donanım düğmesi basmalarını (Ana Sayfa, Geri, Menü, Ses) simüle etme, gücü yönetme, ekran görüntüsü alma ve belirli ekran durumlarını bekleme yöntemleri sağlar. UiDevice test başına bir kez oluşturulur ve tüm işlemler için yeniden kullanılır.
UiSelector, UI öğelerini bulmak için akıcı bir API'dir. Espresso ViewMatchers'ın aksine, UiSelector derleme gerektirmez — arama koşulları bir yöntem zinciri aracılığıyla oluşturulur: text(), className(), description(), resourceId(), index(). Birden çok koşul, mantıksal VE aracılığıyla otomatik olarak birleştirilir.
| UiSelector Yöntemi | Amaç |
|---|---|
| text(String) | Tam öğe metnine göre arama |
| textContains(String) | Kısmi metin eşleşmesine göre arama |
| resourceId(String) | Kaynak kimliğine göre arama (örn. com.example:id/button) |
| className(String) | View sınıf adına göre arama |
| description(String) | content-description'a göre arama |
| childSelector(selector) | Bir kapsayıcı içinde alt öğe arama |
Ekranda aynı metne sahip birden çok öğe olduğunda, UiSelector kriterleri birleştirmeye izin verir: kimliğe göre bir kapsayıcı bulun, ardından içinde — metin ve sınıfa göre bir öğe. Bu, istenen bileşenin benzersiz şekilde tanımlanmasını sağlar. childSelector yöntemi, arama kapsamını belirli bir kapsayıcıya daraltarak UI ağacında gezinmeyi hızlandırır.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// Listenin içinde, "Wi-Fi" metnine sahip öğeyi bul
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
Uygulamalar arası test, UI Automator'ın seçilmesinin ana nedenidir. Framework, uygulamalar arasında geçiş yapabilir, tarayıcı üzerinden OAuth girişini test edebilir, sistem diyaloglarını (izinler, uygulama seçici) kontrol edebilir ve sistem durum çubuğu, bildirim paneli ve kilit ekranıyla etkileşime girebilir.
Tipik bir uygulamalar arası test senaryosu: uygulama OAuth yetkilendirmesi için bir tarayıcı açar, kullanıcı kullanıcı adını ve şifresini girer ve tarayıcı uygulamaya geri yönlendirir. UI Automator süreçler arasında geçiş yapar, tarayıcıdaki giriş alanlarını bulur, doldurur ve “Oturum Aç” düğmesine dokunur.
// Tarayıcının görünmesini bekleme
device.wait(Until.hasObject(
UiSelector().packageName("com.android.chrome")
), 5000)
// Tarayıcıda e-posta giriş alanını arama
val emailField = device.findObject(
UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"
UI Automator sistem diyaloglarını kontrol edebilir ve kapatabilir — konum izinleri, bildirimler, dosya erişimi. Bu, sistemin sırayla birden çok izin istediği ilk başlatma senaryolarını test etmek için kritik öneme sahiptir. UI Automator olmadan, bu tür senaryolar otomatikleştirilemez çünkü sistem diyalogları uygulamanın sürecine ait değildir.
Seçim UI Automator ve Espresso arasında test senaryosuna bağlıdır. Espresso, otomatik senkronizasyon ve minimum ek kodla tek bir uygulamayı test etmek için optimize edilmiştir. UI Automator, sistem, tarayıcı veya birden çok uygulamayla etkileşim gerektiren senaryolar için uygundur.
| Kriter | UI Automator | Espresso |
|---|---|---|
| Kapsam | Tüm cihaz, birden çok uygulama | Tek uygulama |
| Senkronizasyon | Manuel (bekle, uyu) | Otomatik (Idling Resource) |
| Hız | Daha yavaş (hizmet üzerinden erişim) | Daha hızlı (süreç içinde çalışır) |
| Sistem UI | Destekler (Bildirimler, Hızlı Ayarlar) | Desteklemez |
| Arama Hassasiyeti | Niteliğe göre UiSelector | Tür ve hiyerarşiye göre ViewMatchers |
| Kararlılık | Daha düşük (zamanlamaya bağlı) | Daha yüksek (otomatik bekleme) |
Pratikte, bu framework'ler genellikle birlikte kullanılır: Espresso, yüksek kararlılıkla ana uygulamanın UI testlerini kapsar, UI Automator ise uygulama sınırlarının ötesine geçen senaryolar için kullanılır — OAuth girişi, sistem izinleri, Share Intent ile çalışma. Bu kombinasyon, minimum test bakım maliyetiyle maksimum UI kapsamı sağlar.
Entegrasyon build.gradle'a bir bağımlılık eklenerek yapılır. Framework, AndroidX Test'in bir parçasıdır ve manifest'te ek izin gerektirmez — Accessibility Service'e erişim, araçlı test başlatıldığında otomatik olarak yapılandırılır.
Minimum yapılandırma, uiautomator yapıtını ve standart AndroidJUnitRunner test çalıştırıcısını içerir. UI Automator testleri src/androidTest dizinine yerleştirilir ve Android API 18+ çalıştıran bir öykünücü veya fiziksel cihazda çalıştırılır.
dependencies {
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test:runner:1.6.1")
}
Bir UiDevice örneği elde etmek için InstrumentationRegistry.getInstrumentation() kullanılır. UiDevice, setUp() yönteminde bir kez oluşturulmalı ve cihaz kaynaklarını korumak için sınıfın tüm testlerinde yeniden kullanılmalıdır. UiDevice'in thread-safe olmadığını unutmamak önemlidir — tüm işlemler test yönteminin aynı iş parçacığında gerçekleştirilmelidir. Her testte yeni bir UiDevice oluşturmak ek yük oluşturur ve yürütmeyi yavaşlatır. beforeClass yönteminde bir kez UiDevice oluşturulması ve test sınıfının tüm testleri için yeniden kullanılması önerilir.
Espresso'nun aksine, UI Automator'da otomatik senkronizasyon yoktur. Öğelerin görünmesini beklemek için UiDevice.wait(condition, timeout) yöntemi bir Until nesnesiyle kullanılır: Until.findObject(selector), Until.hasObject(selector), Until.gone(selector). Uygun beklemeler olmadan, yarış koşulları nedeniyle testler kararsız hale gelir — arama anında bir öğe ekranda görünmemiş olabilir. Kararlılık için en az 3–5 saniyelik bir zaman aşımı ayarlanması önerilir.
Sıkça Sorulan Sorular
UI Automator, Accessibility Service düzeyinde çalışır ve herhangi bir uygulamayla etkileşime girebilir. Espresso, tek bir uygulamanın süreci içinde çalışır ve UI iş parçacığıyla otomatik senkronizasyon kullanır. UI Automator uygulamalar arası senaryolar için daha iyidir, Espresso ise kararlı tek uygulama testleri için daha iyidir.
Evet, UI Automator Android API 18+ çalıştıran tüm cihazlarda çalışır. Kök erişimi gerektirmez — testler başlatıldığında Instrumentation aracılığıyla etkinleştirilen standart Accessibility Service'i kullanır.
UI Automator, mevcut ekranın tam UI bileşen ağacını almak için Accessibility Service'i kullanır. Ardından UiSelector bu ağacı geçer ve belirtilen kriterlere göre öğeleri bulur: metin, sınıf, kimlik, content-description veya bunların bir kombinasyonu.
Evet, UiDevice.takeScreenshot(storePath) yöntemi mevcut ekranın ekran görüntüsünü almayı ve bir dosyaya kaydetmeyi sağlar. Bu, hata ayıklama için kullanışlıdır: bir test başarısız olduğunda, ekran görüntüsünü kaydedebilir ve ekran durumunu analiz edebilirsiniz.
UI Automator'da otomatik senkronizasyon yoktur, bu nedenle testler zamanlamaya duyarlıdır. Bir animasyon tamamlanmamışsa veya bir View henüz oluşturulmamışsa, findObject öğeyi bulamayabilir. Çözüm, yeterli zaman aşımıyla UiDevice.wait() kullanmaktır.
Özet
UI Automator araç seti, tüm temel uygulamalar arası test senaryolarını kapsar ve sistem düzeyinde Android otomasyonu için standarttır.
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun