O Compose é integrado a frameworks de teste comuns.
Interoperabilidade com o Espresso
Em um app híbrido, é possível encontrar componentes do Compose dentro de hierarquias de visualização e
visualizações dentro dos elementos do Compose (com o elemento AndroidView).
Não há etapas específicas que sejam necessárias para fazer correspondência a nenhum dos tipos. A correspondência de visualizações é feita usando o método
Espresso's onView e os elementos do Compose com 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()))
}
Adicionar semântica com escopo de visualização para testes de interoperabilidade do Compose
Definir o escopo das pesquisas do Compose para visualizações específicas
Ao migrar interfaces complexas para o Compose, você pode encontrar elementos idênticos do Compose aninhados em várias visualizações tradicionais do Android, como em um RecyclerView ou um ViewPager. Nesses cenários, uma pesquisa padrão do Compose
como onNodeWithText("Save")pode falhar com um erro "Vários nós encontrados".
Em vez de modificar o código de produção para injetar tags de teste dinâmicas para distinguir esses elementos, você pode definir o escopo do teste do Compose diretamente para uma visualização específica do Android.
Use a API onRootWithViewInteraction na regra de teste. Essa função aceita uma ViewInteraction do Espresso, permitindo que você aproveite o Espresso para isolar uma visualização de contêiner específica e realizar interações do Compose exclusivamente nessa hierarquia com escopo.
Interagir com um item de lista
Se você precisar interagir com um elemento do Compose em uma linha RecyclerView específica, use o Espresso para localizar a linha e, em seguida, defina o escopo da interação do Compose.
Isso ignora elementos idênticos do Compose em todas as outras linhas.
@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() }
Resolver ambiguidades em ViewPagers
Quando vários fragmentos com layouts idênticos do Compose estão na memória simultaneamente, você pode definir o escopo da pesquisa para o ID da visualização raiz do fragmento específico para evitar ambiguidades de correspondência.
@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() }
Interoperabilidade com o UiAutomator
Por padrão, os elementos combináveis podem ser acessados no UiAutomator apenas pelos
descritores convenientes (texto mostrado, descrição do conteúdo etc.). Caso queira
acessar um elemento combinável que use Modifier.testTag, é necessário ativar
a propriedade semântica testTagsAsResourceId para a subárvore de elementos combináveis específicos. Ativar esse comportamento é útil para elementos combináveis que não têm nenhum outro elemento exclusivo, por exemplo, elementos roláveis como a LazyColumn.
Ative a propriedade semântica apenas uma vez na hierarquia dos elementos de composição para garantir que todos os elementos de composição aninhados com Modifier.testTag possam ser acessados pelo 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
}
}
Todos os elementos de composição com o Modifier.testTag(tag) podem ser acessados com o uso
de By.res(resourceName) usando o mesmo tag que o resourceName.
val device = UiDevice.getInstance(getInstrumentation())
val lazyColumn: UiObject2 = device.findObject(By.res("myLazyColumn"))
// Some interaction with the lazyColumn.
Outros recursos
- Testar apps no Android: a página de destino principal de testes do Android oferece uma visão mais ampla dos fundamentos e técnicas de teste.
- Conceitos básicos de testes: Saiba mais sobre os conceitos básicos por trás do teste de um app Android.
- Testes locais: é possível executar alguns testes localmente, na sua estação de trabalho.
- Testes de instrumentação: também é recomendável executar testes de instrumentação. Ou seja, testes executados diretamente no dispositivo.
- Integração contínua: A integração contínua permite integrar seus testes ao pipeline de implantação.
- Testar diferentes tamanhos de tela: Com tantos dispositivos disponíveis para os usuários, é recomendável testar diferentes tamanhos de tela.
- Espresso: embora seja destinado a interfaces baseadas em visualização, o conhecimento do Espresso ainda pode ser útil para alguns aspectos dos testes do Compose.