Compose uygulamanızı iyi bilinen yaklaşımlar ve kalıplarla test edebilirsiniz.
Yalıtılmış ortamda test etme
ComposeTestRule, bir etkinliği başlatmanıza olanak tanır. Bu etkinlikte, birleştirilebilir öğeler (ör. uygulamanızın tamamı, tek bir ekran veya küçük bir öğe) gösterilir. Ayrıca, composable işlevlerinizin doğru şekilde kapsüllenmiş olduğundan ve bağımsız olarak çalıştığından emin olmak da iyi bir uygulamadır. Bu sayede kullanıcı arayüzü testleri daha kolay ve odaklanmış bir şekilde yapılabilir.
Bu, yalnızca birim kullanıcı arayüzü testleri oluşturmanız gerektiği anlamına gelmez. Kullanıcı arayüzünüzün daha büyük bölümlerini kapsayan kullanıcı arayüzü testleri de çok önemlidir.
Kendi içeriğinizi ayarladıktan sonra etkinliğe ve kaynaklara erişme
Çoğu zaman, test edilen içeriği composeTestRule.setContent kullanarak ayarlamanız ve etkinlik kaynaklarına erişmeniz gerekir. Örneğin, gösterilen metnin bir dize kaynağıyla eşleştiğini onaylamak için. Ancak etkinlik zaten setContent işlevini çağırıyorsa createAndroidComposeRule() ile oluşturulan bir kuralda setContent işlevini çağıramazsınız.
Bunu yapmanın yaygın bir yolu, ComponentActivity gibi boş bir etkinlik kullanarak AndroidComposeTestRule oluşturmaktır.
class MyComposeTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@Test
fun myTest() {
// Start the app
composeTestRule.setContent {
MyAppTheme {
MainScreen(uiState = exampleUiState, /*...*/)
}
}
val continueLabel = composeTestRule.activity.getString(R.string.next)
composeTestRule.onNodeWithText(continueLabel).performClick()
}
}
ComponentActivity öğesinin uygulamanızın AndroidManifest.xml dosyasına eklenmesi gerektiğini unutmayın. Bu özelliği etkinleştirmek için modülünüze şu bağımlılığı ekleyin:
debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")
Özel anlamsal yapı özellikleri
Bilgileri testlere sunmak için özel anlamsal yapı özellikleri oluşturabilirsiniz.
Bunu yapmak için yeni bir SemanticsPropertyKey tanımlayın ve SemanticsPropertyReceiver kullanarak kullanılabilir hale getirin.
// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey
Şimdi bu özelliği semantics değiştiricisinde kullanın:
val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
modifier = Modifier.semantics { pickedDate = datePickerValue }
)
Testlerde, özelliğin değerini onaylamak için SemanticsMatcher.expectValue kullanın:
composeTestRule
.onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
.assertExists()
Durum geri yüklemeyi doğrulama
Etkinlik veya işlem yeniden oluşturulduğunda Oluşturma öğelerinizin durumunun doğru şekilde geri yüklendiğini doğrulayın. StateRestorationTester sınıfıyla etkinlik yeniden oluşturmaya güvenmeden bu tür kontrolleri gerçekleştirin.
Bu sınıf, composable'ların yeniden oluşturulmasını simüle etmenize olanak tanır. Bu, özellikle rememberSaveable uygulamasını doğrulamak için kullanışlıdır.
class MyStateRestorationTests {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun onRecreation_stateIsRestored() {
val restorationTester = StateRestorationTester(composeTestRule)
restorationTester.setContent { MainScreen() }
// TODO: Run actions that modify the state
// Trigger a recreation
restorationTester.emulateSavedInstanceStateRestore()
// TODO: Verify that state has been correctly restored.
}
}
Farklı cihaz yapılandırmalarını test etme
Android uygulamalarının pencere boyutları, yerel ayarlar, yazı tipi boyutları, koyu ve açık temalar gibi birçok değişen koşula uyum sağlaması gerekir. Bu koşulların çoğu, kullanıcı tarafından kontrol edilen ve mevcut Configuration örneğiyle sunulan cihaz düzeyindeki değerlerden türetilir. Testin cihaz düzeyindeki özellikleri yapılandırması gerektiğinden, farklı yapılandırmaları doğrudan bir testte test etmek zordur.
DeviceConfigurationOverride, yalnızca test için kullanılan bir API'dir. Bu API, test edilen @Composable içeriği için farklı cihaz yapılandırmalarını yerelleştirilmiş bir şekilde simüle etmenize olanak tanır.
DeviceConfigurationOverride öğesinin yardımcı nesnesi, cihaz düzeyindeki yapılandırma özelliklerini geçersiz kılan aşağıdaki uzantı işlevlerine sahiptir:
DeviceConfigurationOverride.DarkMode(): Sistemi geçersiz kılarak koyu tema veya açık tema kullanılır.DeviceConfigurationOverride.FontScale(): Sistem yazı tipi ölçeğini geçersiz kılar.DeviceConfigurationOverride.FontWeightAdjustment(): Sistem yazı tipi ağırlığı ayarını geçersiz kılar.DeviceConfigurationOverride.ForcedSize(): Cihaz boyutundan bağımsız olarak belirli bir alan miktarını zorunlu kılar.DeviceConfigurationOverride.LayoutDirection(): layout direction (soldan sağa veya sağdan sola) özelliğini geçersiz kılar.DeviceConfigurationOverride.Locales(): Yerel ayarı geçersiz kılar.DeviceConfigurationOverride.RoundScreen(): Ekran yuvarlaksa geçersiz kılar.
Belirli bir geçersiz kılmayı uygulamak için test edilen içeriği DeviceConfigurationOverride() üst düzey işlevine yapılan bir çağrıya sarın ve uygulanacak geçersiz kılmayı parametre olarak iletin.
Örneğin, aşağıdaki kod, yoğunluğu yerel olarak değiştirmek için DeviceConfigurationOverride.ForcedSize() geçersiz kılma işlemini uygular ve testin üzerinde çalıştırıldığı cihaz bu pencere boyutunu doğrudan desteklemese bile MyScreen composable'ın büyük bir yatay pencerede oluşturulmasını zorlar:
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } }
Birden fazla geçersiz kılmayı birlikte uygulamak için DeviceConfigurationOverride.then() kullanın:
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.FontScale(1.5f) then DeviceConfigurationOverride.FontWeightAdjustment(200) ) { Text(text = "text with increased scale and weight") } }
Testlerde özel hata işleme
Kullanıcı arayüzü testlerinde hata ayıklama işlemi genellikle bir onaylama başarısız olduğunda ekran durumunun ve kompozisyon hiyerarşisinin incelenmesini gerektirir.
Compose, teşhisleri kolaylaştırmak için yerel bir hata işleme ardışık düzeni sağlar. Hata oluştuğunda ekran görüntülerini ve kullanıcı arayüzü hiyerarşilerini otomatik olarak yakalayabilir veya kilitlenme telemetrisini harici araçlara yönlendirmek için özel işleyiciler kaydedebilirsiniz.
Hata işlemeyi yapılandırma
Hata işlemeyi yapılandırmak için TestFailurePolicy nesnesini ComposeUiTestConfig'a iletin.
Yerleşik hata çıktılarını yakalama
Test başarısız olduğunda ekran görüntülerini ve kullanıcı arayüzü hiyerarşilerini yakalamak için TestFailurePolicy içinde screenshotCaptureMode ve uiHierarchyCaptureMode özelliklerini ayarlayın.
class MyComposeTest { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, uiHierarchyCaptureMode = TestFailurePolicy.CaptureMode.Enabled ) ) @Test fun myFirstTest() = runComposeUiTest(config = customConfig) { // ... } }
Özel hata işleyici kullanma
Test hataları için özel davranış tanımlamak istiyorsanız failureHandlers listesine TestFailureHandler ekleyin. Her işleyici, orijinal hatayı ve önceki ardışık düzen işleyicileri tarafından oluşturulan yapıların listesini içeren bir FailureContext nesnesi alır.
class MyComposeTestWithHandler { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, failureHandlers = listOf( TestFailureHandler { context -> val screenshot = context.artifacts.firstOrNull { it.type == FailureArtifact.Type.Screenshot } // ... } ) ) ) @get:Rule val rule = createComposeRule(config = customConfig) // ... }
Bir test paketinin tamamı için yakalamaları yapılandırma
Modülünüzün build.gradle dosyasına enstrümantasyon çalıştırıcı bağımsız değişkenleri ileterek tüm test paketi için hata yapısı yakalamalarını etkinleştirebilirsiniz. Bu sayede, test dosyalarını tek tek güncellemeniz gerekmez.
// build.gradle.kts
android {
defaultConfig {
// ...
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isUiHierarchyCaptureEnabled"] = "true"
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isScreenshotCaptureEnabled"] = "true"
}
}
Yapılandırma önceliği
Çerçeve hem yerel TestFailurePolicy hem de paket düzeyindeki çalıştırıcı bağımsız değişkenlerini değerlendirir:
- Test
failurePolicyiçinde bir modu açıkçaCaptureMode.Enabled/Disabledolarak ayarlarsanız bu, çalıştırıcı bağımsız değişkenini geçersiz kılar. - Bir modu
CaptureMode.Unspecifiedolarak ayarlarsanız (veyafailurePolicy'ınullolarak bırakırsanız) çerçeve, çalıştırıcı bağımsız değişkenine geri döner.
Ek Kaynaklar
- Android'de uygulamaları test etme: Android testleriyle ilgili ana açılış sayfası, testlerle ilgili temel bilgiler ve teknikler hakkında daha geniş bir bakış açısı sunar.
- Testlerle ilgili temel bilgiler: Android uygulamasını test etmeyle ilgili temel kavramlar hakkında daha fazla bilgi edinin.
- Yerel testler: Bazı testleri kendi iş istasyonunuzda yerel olarak çalıştırabilirsiniz.
- Enstrümanlı testler: Enstrümanlı testler de çalıştırmak iyi bir uygulamadır. Yani doğrudan cihaz üzerinde çalışan testler.
- Sürekli entegrasyon: Sürekli entegrasyon, testlerinizi dağıtım ardışık düzeninize entegre etmenize olanak tanır.
- Farklı ekran boyutlarını test edin: Kullanıcıların erişebileceği çok sayıda cihaz olduğundan farklı ekran boyutlarını test etmeniz gerekir.
- Espresso: Görüntüleme tabanlı kullanıcı arayüzleri için tasarlanmış olsa da Espresso bilgisi, Compose testinin bazı yönleri için faydalı olabilir.