Совместимость

Compose интегрируется с распространенными фреймворками для тестирования.

Совместимость с Espresso

В гибридном приложении компоненты Compose можно найти внутри иерархий представлений, а представления — внутри составных элементов Compose (через составной элемент AndroidView ).

Для сопоставления обоих типов не требуется никаких специальных действий. Сопоставление представлений осуществляется с помощью onView в Espresso, а сопоставление элементов Compose — с помощью правила ComposeTestRule .

@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.

Область действия. Создание поисковых запросов для конкретных представлений.

При переносе сложных пользовательских интерфейсов в Compose вы можете столкнуться с идентичными элементами Compose, вложенными в несколько традиционных представлений Android — например, в RecyclerView или ViewPager . В таких сценариях стандартный поиск Compose, например, onNodeWithText("Save") может завершиться ошибкой "Найдено несколько узлов".

Вместо того чтобы изменять рабочий код для внедрения динамических тегов тестов, позволяющих различать эти элементы, вы можете ограничить область действия теста Compose конкретным представлением Android.

Используйте API onRootWithViewInteraction в своем правиле тестирования. Эта функция принимает объект Espresso ViewInteraction , что позволяет использовать Espresso для изоляции конкретного контейнерного представления и выполнения взаимодействий Compose исключительно в рамках этой иерархической области видимости.

Взаимодействие с элементом списка

Если вам необходимо взаимодействовать с элементом Compose внутри определенной строки RecyclerView , используйте Espresso для поиска этой строки, а затем ограничьте область действия вашего взаимодействия с Compose этой строкой. При этом идентичные элементы Compose во всех остальных строках будут игнорироваться.

@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()
}

Разрешение неоднозначностей в ViewPagers

Когда в памяти одновременно находится несколько фрагментов с одинаковыми макетами Compose, вы можете ограничить поиск идентификатором корневого представления конкретного фрагмента, чтобы избежать неоднозначности совпадения.

@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

По умолчанию доступ к составным элементам из UiAutomator возможен только по их удобным дескрипторам (отображаемый текст, описание содержимого и т. д.). Если вы хотите получить доступ к любому составному элементу, использующему Modifier.testTag , вам необходимо включить семантическое свойство testTagsAsResourceId для поддерева конкретного составного элемента. Включение этого поведения полезно для составных элементов, которые не имеют других уникальных идентификаторов, например, для прокручиваемых составных элементов (например, LazyColumn ).

Включайте семантическое свойство только один раз, когда оно находится на более высоком уровне иерархии ваших компонуемых объектов, чтобы гарантировать доступность всех вложенных компонуемых объектов с Modifier.testTag из UiAutomator.

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) может быть доступен с помощью By.res(resourceName) используя тот же tag что и resourceName .

val device = UiDevice.getInstance(getInstrumentation())

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

Дополнительные ресурсы

  • Тестирование приложений на Android : Главная страница, посвященная тестированию Android, предоставляет более широкий обзор основ и методов тестирования.
  • Основы тестирования : Узнайте больше об основных концепциях тестирования Android-приложений.
  • Локальные тесты : Вы можете запустить некоторые тесты локально, на своей рабочей станции.
  • Инструментальные тесты : Рекомендуется также запускать инструментальные тесты, то есть тесты, которые выполняются непосредственно на устройстве.
  • Непрерывная интеграция : Непрерывная интеграция позволяет интегрировать ваши тесты в конвейер развертывания.
  • Протестируйте разные размеры экрана : учитывая большое количество доступных пользователям устройств, следует протестировать их работу на экранах разных размеров.
  • Espresso : Хотя этот язык программирования предназначен для пользовательских интерфейсов на основе представлений, знание Espresso может быть полезно и для некоторых аспектов тестирования с помощью Compose.