Android Uygulamalarında Unit ve UI Testleri — Pratik Bir Rehber
Kısa cevap: Önce mantığı unit testleriyle (JVM) kapsayın, ardından UI testlerini (Espresso/Compose) ekleyin ve her şeyi Gradle aracılığıyla CI'da çalıştırın; geniş ölçekli test çalıştırmaları için Firebase Test Lab'i kullanın. Aşağıda, projenizde doğrudan uygulayabileceğiniz adım adım talimatlar yer almaktadır.
İçindekiler {{TOC_AUTOMATIC}}
Unit testleri nedir ve nasıl yazılır?
Unit testleri, kullanıcı arayüzünü ve harici servisleri başlatmadan küçük kod birimlerini (metotlar, sınıflar) kontrol eder. Avantajları: hızlıdırlar, CI için uygundur ve erken geri bildirim sağlarlar.
Nasıl Başlanır
- Testleri app/src/test/java dizinine yerleştirin.
- JUnit 5 (@Test, @BeforeEach anotasyonları) + assertEquals/assertThrows kullanın.
- Mocklama: Mockito veya MockK (Kotlin için). Coroutine'ler için kotlinx-coroutines-test kütüphanesinden runTest kullanın.
Basit bir test örneği (Kotlin):
class CalculatorTest {
@Test
fun `calculateTotal with valid inputs returns correct sum`() {
val calc = Calculator()
val result = calc.calculateTotal(100.0, 0.2)
assertEquals(120.0, result, 0.001)
}
}
Kod Kapsamı ve Metrikler
- JaCoCo'yu entegre edin: unit testleri için hedef %70–90 olmalıdır.
- Testleri yerel olarak ve CI'da çalıştırın (./gradlew testDebugUnitTest).
- Sınır durumları için testler yazın: sıfırlar, negatif değerler, null (uygulanabilirse).
Commit işleminden önce unit testlerini çalıştırın; bu, hata ayıklama süresini azaltır ve regresyon olasılığını düşürür.
UI Testleri: Espresso, Compose Testing ve Ortam
UI testleri, kullanıcı eylemlerini taklit eder: giriş yapma, tıklama, gezinme. Daha yavaş çalışırlar ancak ekran entegrasyonunu ve cihaz üzerindeki davranışı doğrularlar.
Araç Seçimi
- Espresso — Klasik View tabanlı UI için, black-box testi için güvenilirdir.
- Compose Testing — UI Jetpack Compose ile oluşturulmuşsa; hızlıdır ve semantiği kontrol etmeye olanak tanır.
- UI Automator — Uygulamalar arası etkileşim veya sistem diyalogları için.
Nerede Yazılır ve Çalıştırılır
- Test kodu: app/src/androidTest/java.
- Çalıştırma: Yerel cihazlar/emülatörler için ./gradlew connectedAndroidTest.
- CI/bulut tabanlı çalıştırmalar için: Firebase Test Lab entegrasyonu (runInstrumentationTests).
Örnek Senaryolar
- Giriş: yanlış şifre, tekrar denemeler, oturum kaydetme.
- Gezinme: doğru geri tuşu mantığı ve yapılandırma değişikliği sırasında durum yönetimi.
- Sınır Durumları: ağ kaybı, yavaş yanıtlar, ekran yönü değişimi.
Kararsız (flaky) testleri görmezden gelmeyin: seed değerlerinin sabitlenmesi, zaman aşımlarının stabilize edilmesi ve harici servislere bağımlılığın en aza indirilmesi kritiktir.
Araçlar ve CI/CD Entegrasyonu
Araç Önerileri
- Unit: JUnit 5, Mockito/MockK, Kotest (BDD/Kotlin yerel testleri için).
- UI: Espresso, Compose Testing, UI Automator.
- Kod Kapsamı: JaCoCo.
- Bulut Tabanlı Test: Firebase Test Lab (çok sayıda cihaz ve API seviyesi).
CI için Gradle Görev Örnekleri
- Unit: ./gradlew testDebugUnitTest
- Bağlı cihazda UI: ./gradlew connectedAndroidTest
- Kod kapsamı raporu: ./gradlew jacocoTestReport
CI Stratejisi
- Her PR'da unit testleri (hızlı).
- UI: gecelik veya sürüm başına; kritik UI testleri PR'da çalıştırılabilir ancak daha ekonomik olanı smoke test setidir.
- CI/Firebase'de cihaz matrisi kullanın: Android API, ekran boyutları, yoğunluk.
Sık Yapılan Hatalar
- Özel metotları test etmek — genellikle gereksizdir; uygulamayı değil, davranışı test edin.
- Kodda statik bağımlılıklar ve global singleton'lar — mocklamayı zorlaştırır. Bağımlılıkları tersine çevirin.
- Çoklu iş parçacığını (multithreading) göz ardı etmek: coroutine'ler için runTest ve TestDispatcher kullanın.
- UI'da açık senkronizasyonlar yerine zamana dayalı bekleme (Idling Resources veya composeTestRule.waitForIdle() kullanın).
- Kararlı test ortamının eksikliği — sahte yanıtları ve yerel fake repository'leri hazır tutun.
SSS
- Test sıralaması nasıl olmalı? Unit ile başlayın, ardından entegrasyon ve UI testlerine geçin; bu, çaba/sonuç oranını en iyi hale getirir.
- %100 kod kapsamı gerekli mi? Hayır. Amaç, kritik alanları kapsamaktır: iş mantığı ve kritik senaryolar; unit testlerde %70–90 ve UI testlerinde %50+ makul bir hedeftir.
- Kararsız testler nasıl azaltılır? Random seed değerini sabitleyin, harici bağımlılıkları kaldırın, kararlı test verileri ve idling mekanizmaları kullanın.
Bu uygulamalarla stabil derlemeler ve öngörülebilir sürümler elde edersiniz: önce unit testlerine yatırım yapın (%20 çabayla %80 güven), ardından UI test çalışmalarını ve CI'yı otomatikleştirin.