UI testi, mobil uygulamanın kullanıcı arayüzü öğelerinin — düğmeler, metin alanları, listeler ve gezinme bileşenleri — görüntülenme ve etkileşim doğruluğunu kontrol eder. İş mantığını kontrol eden birim testlerinin aksine, UI testleri kullanıcı eylemlerini simüle eder: dokunmalar, kaydırmalar, metin girişi ve arayüz yanıtını doğrular. Android Developers, 2024 tarafından yapılan bir araştırmaya göre, UI testi kritik kullanıcı senaryolarının %70'ini kapsar ve mantıksal kontrollerle erişilemeyen düzen kusurlarını tespit etmeyi sağlar.
Önemli Noktalar
UI testi, test kodunun uygulamanın grafik arayüzüyle gerçek bir kullanıcının yapacağı gibi etkileşime girdiği bir otomatik doğrulama türüdür. Test, ekranda bir öğe — düğme, metin alanı, liste — bulur, üzerinde bir eylem gerçekleştirir ve beklenen arayüz yanıtını doğrular. Örneğin, yanlış bir şifre girdikten sonra, bir UI testi ekranda doğru metne sahip bir hata mesajının görünüp görünmediğini kontrol eder.
UI testleri ile diğer otomasyon türleri arasındaki temel fark, uygulamanın dahili API'leri aracılığıyla değil, işletim sisteminin Erişilebilirlik katmanı aracılığıyla çalışmalarıdır. Bu, UI testlerinin arayüzü tam olarak bir kullanıcı ve ekran okuyucunun gördüğü gibi gördüğü anlamına gelir. Bu sayede UI testleri yalnızca işlevselliği değil, aynı zamanda öğelerin erişilebilirliğini — WCAG gereksinimlerine uygunluğu — da doğrular.
JetBrains Developer Ecosystem 2023 anketine göre, mobil ekiplerin %58'i CI/CD boru hatlarında UI testleri kullanmaktadır. Ticari projelerde ortalama UI testi kapsamı, uygulama ekranlarının %30–40'ıdır. UI testleri olan projeler, arayüz çökmeleriyle ilgili uygulama mağazalarında %25 daha az olumsuz değerlendirme alır.
UI testleri ile birim testleri arasındaki temel fark, soyutlama seviyesidir. Birim testleri, Android veya iOS çerçevesinden izole edilmiş bireysel sınıflar ve işlevlerle çalışır. JVM'de (Android için) bir öykünücü başlatmadan çalışırlar ve milisaniyeler sürer. UI testleri gerçek bir cihazda veya öykünücüde çalışır, sistem hizmetleriyle etkileşime girer ve senaryo başına saniyeler veya dakikalar alır.
Testlerin hedef kitlesi de farklıdır. UI testleri uçtan uca kullanıcı senaryolarını doğrular — kayıt, sipariş verme, arama. Birim testleri iş mantığını kapsar: hesaplamalar, doğrulama, veri dönüşümü. Bir UI testi vergi hesaplamasının doğruluğunu kontrol etmez — toplam tutarın ekranda görüntülenip görüntülenmediğini kontrol eder. Hesaplamanın kendisi bir birim testi tarafından doğrulanır.
Google Testing Blog (2020)'e göre, bir projedeki optimal test oranı test piramidi kuralını izler: %70 birim testleri, %20 entegrasyon testleri ve %10 UI testleri. Bu oranın UI testleri lehine ihlal edilmesi, çalıştırma süresinin artmasına ve test paketinin kırılganlaşmasına yol açar, çünkü UI testleri ekran düzenindeki değişikliklere karşı hassastır.
Android için baskın çerçeve Espresso'dur — AndroidX Test'e gömülü Google kütüphanesi. Espresso, bir sonraki doğrulamayı gerçekleştirmeden önce animasyonların ve arka plan görevlerinin tamamlanmasını bekleyerek otomatik olarak UI iş parçacığıyla senkronize olur. Jetpack Compose için, geleneksel görünüm tanımlayıcıları yerine anlamsal düğümler aracılığıyla çalışan Compose UI Test uzantısı kullanılır.
iOS için birincil araç, Xcode'un bir parçası olan XCUITest'tir. Testler Swift dilinde yazılır ve öğeleri bulmak için Erişilebilirlik tanımlayıcılarını kullanır. XCUITest, kayıt işlevi aracılığıyla test kaydını ve xcodebuild aracılığıyla CI sistemleriyle entegrasyonu destekler. Platformlar arası projeler için, WebDriver protokolüne dayalı ve minimum kod değişikliğiyle Android ve iOS'ta aynı testleri çalıştırmaya izin veren Appium kullanılır.
Espresso, onView ve kaynak kimliği tanımlayıcıları aracılığıyla geleneksel Görünüm sistemiyle çalışır. Compose UI Test, anlamsal bir katman kullanarak testlerin görünüm hiyerarşisine daha az bağımlı olmasını sağlar. Örneğin, Espresso'da düğme bulma: onView(withId(R.id.submit)), Compose'da: onNodeWithTag(“submit”). Compose testleri, yeniden oluşturmayı otomatik olarak yönetir ve açık boşta kalma durumu beklemesi gerektirmez.
XCUITest, giriş noktası olarak XCUIApplication'ı kullanır. Her arayüz öğesi, Erişilebilirlik özellikleri aracılığıyla bulunur: programatik erişim için accessibilityIdentifier ve VoiceOver için accessibilityLabel. Çerçeve, Xcode'un kayıt işlevi aracılığıyla test kaydını destekler — geliştirici simülatörde eylemler gerçekleştirir ve Xcode test kodunu oluşturur. Hazır testler xcodebuild test aracılığıyla çalıştırılır.
Appium, WebDriver protokolüne dayanır ve herhangi bir dili destekler: Java, Python, JavaScript. Öğe arama stratejileri arasında id, xpath, class name ve accessibility id bulunur. Appium, sunucu kurulumu ve Desired Capabilities — platformName, deviceName, appPackage — yapılandırması gerektirir. Bir alternatif, YAML senaryoları kullanan ve test kodu derlemesi gerektirmeyen Maestro'dur.
Aynı senaryo — uygulamada oturum açma — için üç farklı çerçevede UI testlerini inceleyelim: Android için Espresso, iOS için XCUITest ve platformlar arası yaklaşım için Appium. Senaryo: kullanıcı adı ve şifre girin, giriş düğmesine basın, hoş geldiniz mesajının görüntülenmesini doğrulayın.
Espresso testi, bir öğeyi tanımlayıcısına göre bulmak için onView ve bir eylem gerçekleştirmek için perform kullanır. isDisplayed eşleştiricisiyle check yöntemi, öğenin ekranda görünür olduğunu onaylar.
@RunWith(AndroidJUnit4::class)
class LoginUiTest {
@Rule
@JvmField
val composeTestRule = createComposeRule()
@Test
fun login_withValidCredentials_showsWelcome() {
composeTestRule
.onNodeWithTag("emailField")
.performTextInput("user@example.com")
composeTestRule
.onNodeWithTag("passwordField")
.performTextInput("secret123")
composeTestRule
.onNodeWithTag("loginButton")
.performClick()
composeTestRule
.onNodeWithText("Hoş Geldiniz, Kullanıcı!")
.assertIsDisplayed()
}
}
XCUITest, Erişilebilirlik tanımlayıcıları aracılığıyla arayüz öğelerine erişmek için XCUIApplication'ı kullanır. tap() ve exists yöntemleri etkileşim ve doğrulama sağlar.
class LoginUITests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
continueAfterFailure = false
app.launch()
}
func testLogin_withValidCredentials_showsWelcome() {
app.textFields["emailField"].tap()
app.textFields["emailField"].typeText("user@example.com")
app.secureTextFields["passwordField"].tap()
app.secureTextFields["passwordField"].typeText("secret123")
app.buttons["loginButton"].tap()
XCTAssertTrue(app.staticTexts["Welcome, User!"].exists)
}
}
İlk ilke — öğeleri bulmak için metin etiketleri yerine Erişilebilirlik tanımlayıcıları kullanın. Bir düğmenin metni yerelleştirme sırasında değişebilir, ancak tanımlayıcı sabit kalır. Android'de bu, contentDescription özelliğidir; iOS'ta — accessibilityIdentifier. Bu yaklaşım, testleri arayüz dilinden bağımsız hale getirir ve metin yazarlığı değiştiğinde bakım maliyetlerini azaltır.
sleep() ve sabit gecikmelerden kaçının — çerçevenin yerleşik bekleme mekanizmalarını kullanın. Espresso, bir sonraki doğrulamayı gerçekleştirmeden önce animasyonların ve arka plan görevlerinin tamamlanmasını otomatik olarak bekler. XCUITest, zaman aşımı ile XCTAssertTrue sağlar. Açık duraklamalar, testleri daha yavaş ve dengesiz hale getirir, özellikle CI ortamındaki yavaş cihazlarda.
Testleri kritikliğe göre gruplandırın: duman testleri (3–5 temel senaryo) her işlemede çalıştırılır, tam UI test paketi sürümden önce çalıştırılır. Google Testing Blog (2022)'ye göre, CI'da 30 dakikadan uzun süren UI testleri, çalıştırma sıklığını %40 azaltarak erken regresyon tespit aracı olarak etkinliklerini düşürür.
UI testlerinin çeşitli sınırlamaları vardır. Düzen değişikliklerine duyarlılık: bir tanımlayıcıyı, hiyerarşiyi veya öğe türünü değiştirmek, işlevsellik değişmese bile testi bozar. Çözüm, öğe seçicilerini ayrı sınıflarda merkezileştiren Page Object modelini kullanmaktır. Düzen değiştiğinde, düzinelerce test yerine yalnızca bir Page Object dosyası düzeltilir.
Yürütme süresi: gerçek bir cihazda veya öykünücüde çalıştırma, bir birim testinden 10–50 kat daha uzun sürer. Çözüm, Firebase Test Lab veya AWS Device Farm aracılığıyla birden çok cihazda UI testlerini paralel olarak çalıştırmaktır. Dengesizlik (flakiness), animasyonlar, ağ gecikmeleri veya öykünücü durumundan kaynaklanan yaygın bir CI çalıştırma sorunudur. Dengesizlikle mücadele etmek için, başarısız testlerin otomatik yeniden denemeleri ve her test senaryosunun kararlılık analizi kullanılır.
Sıkça Sorulan Sorular
Ortalama bir ekran için 3–5 UI testi yeterlidir: mutlu yol, hata doğrulama, boş durum, yön değişikliği ve Erişilebilirlik kontrolü. Birden çok duruma sahip karmaşık ekranlar — sipariş formları, ayarlar — temel senaryoların tam kapsamı için 10–15 test gerektirebilir.
Evet, Appium ve Maestro, her iki platformda aynı senaryoları çalıştırmaya izin verir. Ancak, yerel çerçeveler — Espresso ve XCUITest — WebDriver vekilleri aracılığıyla kullanılamayan platforma özgü özelliklere daha iyi kararlılık, hız ve erişim sağlar.
Compose için, anlamsal eşleştiricilere sahip Compose UI Test kütüphanesi kullanılır: onNodeWithText, onNodeWithTag, onNodeWithContentDescription. Compose'un anlamsal katmanı, görünüm hiyerarşisini soyutlayarak testleri Görünüm sistemi için geleneksel Espresso'ya kıyasla daha az kırılgan hale getirir.
Temel UI test çalıştırmaları CI'da öykünücülerde yapılır — hızlı ve ucuzdur. Sürümden önce nihai doğrulama, gerçek donanım özelliklerini (farklı çözünürlükler, işletim sistemi sürümleri ve performans) hesaba katmak için Firebase Test Lab aracılığıyla fiziksel cihazlarda yapılmalıdır.
Birden çok cihazda paralel yürütme kullanın, Geliştirici Seçenekleri aracılığıyla öykünücüde animasyonları devre dışı bırakın, modüler bir test mimarisi oluşturun ve her işlemede duman paketini çalıştırın, tam regresyon çalıştırmasını planlayarak veya sürümden önce gerçekleştirin.
Özet
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