O Compose se integra 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 combináveis 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
onView do Espresso 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()))
}
Adição de semântica com escopo de visualização para testes de interoperabilidade do Compose
Escopo de pesquisas do Compose para visualizações específicas
Ao migrar interfaces complexas para o Compose, talvez você encontre elementos idênticos
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
um ViewInteraction do Espresso, permitindo que você use o Espresso para isolar uma
visualização de contêiner específica e realizar interações do Compose exclusivamente dentro
dessa hierarquia com escopo.
Interagir com um item da lista
Se você precisar interagir com um elemento do Compose dentro de uma linha RecyclerView
específica, use o Espresso para localizar a linha e, em seguida, defina o escopo da interação do Compose para ela.
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 ambiguidade em ViewPagers
Quando vários fragmentos com layouts idênticos do Compose estão na memória simultaneamente, é possível definir o escopo da pesquisa para o ID da visualização raiz do fragmento específico para evitar ambiguidade 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 do elemento combinável
específico. 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 combináveis para
garantir que todos os elementos 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 Modifier.testTag(tag) podem ser acessados com
By.res(resourceName) usando a mesma tag do 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 conceitos básicos e das 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 própria estação de trabalho.
- Testes de instrumentação:também é uma boa prática executar testes de instrumentação. Ou seja, testes que são executados diretamente no dispositivo.
- Integração contínua:com a integração contínua, é possível integrar seus testes ao pipeline de implantação.
- Teste diferentes tamanhos de tela:com tantos dispositivos disponíveis para os usuários, é importante testar diferentes tamanhos de tela.
- Espresso: embora seja destinado a interfaces baseadas em visualizações, o conhecimento do Espresso ainda pode ser útil para alguns aspectos dos testes do Compose.