Birlikte çalışabilirlik

Compose, yaygın test çerçeveleriyle entegre olur.

Espresso ile birlikte çalışabilirlik

Karma uygulamalarda, görünüm hiyerarşileri içinde Compose bileşenlerini ve Compose composable'ları içinde görünümleri (AndroidView composable'ı aracılığıyla) bulabilirsiniz.

Her iki türü de eşleştirmek için özel bir işlem yapmanız gerekmez. Görünümleri Espresso'nun onView ile, Compose öğelerini ise ComposeTestRule ile eşleştirirsiniz.

@Test
fun androidViewInteropTest() {
    // Check the initial state of a TextView that depends on a Compose state.
    Espresso.onView(withText("Hello Views")).check(matches(isDisplayed()))
    // Click on the Compose button that changes the state.
    composeTestRule.onNodeWithText("Click here").performClick()
    // Check the new value.
    Espresso.onView(withText("Hello Compose")).check(matches(isDisplayed()))
}

Compose birlikte çalışabilirlik testi için görünüm kapsamlı anlamsal yapı ekleme

Oluşturma aramalarını belirli görünümlerle sınırlama

Karmaşık kullanıcı arayüzlerini Compose'a geçirirken birden fazla geleneksel Android görünümünün (ör. RecyclerView veya ViewPager içinde) içine yerleştirilmiş aynı Compose öğeleriyle karşılaşabilirsiniz. Bu senaryolarda, onNodeWithText("Save") gibi standart bir Oluşturma araması "Birden fazla düğüm bulundu" hatasıyla başarısız olabilir.

Bu öğeleri ayırt etmek için üretim kodunuzu değiştirip dinamik test etiketleri eklemek yerine Compose testinizi doğrudan belirli bir Android görünümüyle sınırlayabilirsiniz.

Test kuralınızda onRootWithViewInteraction API'sini kullanın. Bu işlev, Espresso ViewInteraction kabul eder. Böylece, belirli bir kapsayıcı görünümü yalıtmak ve yalnızca bu kapsamlı hiyerarşi içinde Compose etkileşimleri gerçekleştirmek için Espresso'dan yararlanabilirsiniz.

Liste öğesiyle etkileşimde bulunma

Belirli bir RecyclerView satırın içindeki bir Compose öğesiyle etkileşimde bulunmanız gerekiyorsa satırı bulmak için Espresso'yu kullanın, ardından Compose etkileşiminizi bu satırla sınırlayın. Bu, diğer tüm satırlardaki aynı Oluşturma öğelerini yoksayar.

@Test
fun testComposeButtonInsideRecyclerViewItem() = runComposeUiTest {
    // Scroll to the desired position using Espresso
    Espresso.onView(withId(recyclerViewId))
        .perform(RecyclerViewActions.scrollToPosition<MyViewHolder>(3))

    // Define an Espresso ViewInteraction that uniquely identifies the row
    val rowView = Espresso.onView(
        allOf(
            withId(rootViewId),
            hasDescendant(withText("Item #3"))
        )
    )

    // Scope the Compose search strictly to that specific row View
    onRootWithViewInteraction(rowView)
        .onNode(hasText("Like"))
        .performClick()
}

ViewPager'larda belirsizliği çözme

Bellekte aynı anda aynı Compose düzenine sahip birden fazla parça olduğunda, eşleşme belirsizliğini önlemek için aramayı belirli parçanın kök Görünüm kimliğiyle sınırlayabilirsiniz.

@Test
fun testComposeButtonInsideViewPagerItem() = runComposeUiTest {
    // Swipe to the desired page using Espresso
    Espresso.onView(withId(viewPagerViewId)).perform(swipeLeft())

    // Identify the specific container view using Espresso
    val fragmentB = Espresso.onView(withId(fragmentRootViewId))

    // The generic text "Save" is now unique within this view scope
    onRootWithViewInteraction(fragmentB)
        .onNode(hasText("Save"))
        .assertIsDisplayed()
}

UiAutomator ile birlikte çalışabilirlik

Varsayılan olarak, composable'lara UiAutomator'dan yalnızca uygun tanımlayıcılarıyla (görüntülenen metin, içerik açıklaması vb.) erişilebilir. Modifier.testTag kullanan bir composable'a erişmek istiyorsanız ilgili composable'ın alt ağacı için testTagsAsResourceId semantik özelliğini etkinleştirmeniz gerekir. Bu davranışın etkinleştirilmesi, kaydırılabilir composable'lar (ör. LazyColumn) gibi başka benzersiz tutma yeri olmayan composable'lar için kullanışlıdır.

Modifier.testTag içeren tüm iç içe yerleştirilmiş composable'lara UiAutomator'dan erişilebilmesi için semantik özelliği composable'lar hiyerarşinizde yalnızca bir kez yüksekte etkinleştirin.

Scaffold(
    // Enables for all composables in the hierarchy.
    modifier = Modifier.semantics {
        testTagsAsResourceId = true
    }
){
    // Modifier.testTag is accessible from UiAutomator for composables nested here.
    LazyColumn(
        modifier = Modifier.testTag("myLazyColumn")
    ){
        // Content
    }
}

Modifier.testTag(tag) ile oluşturulan tüm composable'lara, resourceName ile aynı tag kullanılarak By.res(resourceName) ile erişilebilir.

val device = UiDevice.getInstance(getInstrumentation())

val lazyColumn: UiObject2 = device.findObject(By.res("myLazyColumn"))
// Some interaction with the lazyColumn.

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.
  • Testin temelleri: Android uygulaması test etmenin temel kavramları hakkında daha fazla bilgi edinin.
  • Yerel testler: Bazı testleri kendi iş istasyonunuzda yerel olarak çalıştırabilirsiniz.
  • Araçlı testler: Araçlı 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önlerinde faydalı olabilir.