APIs Testing

Há três maneiras principais de interagir com elementos da interface:

  • Os finders permitem selecionar um ou vários elementos (ou nós na árvore semântica) para fazer declarações ou executar ações.
  • As declarações são usadas para verificar se os elementos existem ou têm determinados atributos.
  • As ações injetam eventos de usuário simulados nos elementos, como cliques ou outros gestos.

Algumas APIs aceitam um SemanticsMatcher para se referir a um ou mais nós na árvore semântica.

Finders

É possível usar onNode e onAllNodes para selecionar um ou vários nós, respectivamente. Você também pode usar finders de conveniência para as pesquisas mais comuns, como onNodeWithText e onNodeWithContentDescription. Confira a lista completa na página de referência de testes do Compose.

Selecionar um único nó

composeTestRule.onNode(<<SemanticsMatcher>>, useUnmergedTree = false): SemanticsNodeInteraction
// Example
composeTestRule
    .onNode(hasText("Button")) // Equivalent to onNodeWithText("Button")

Selecionar vários nós

composeTestRule
    .onAllNodes(<<SemanticsMatcher>>): SemanticsNodeInteractionCollection
// Example
composeTestRule
    .onAllNodes(hasText("Button")) // Equivalent to onAllNodesWithText("Button")

Árvore não mesclada

Alguns nós mesclam informações de semântica dos filhos deles. Por exemplo, um botão com dois elementos do texto mescla os rótulos dos elementos do texto:

MyButton {
    Text("Hello")
    Text("World")
}

Em um teste, use printToLog() para mostrar a árvore semântica:

composeTestRule.onRoot().printToLog("TAG")

Esse código gera a seguinte saída:

Node #1 at (...)px
 |-Node #2 at (...)px
   Role = 'Button'
   Text = '[Hello, World]'
   Actions = [OnClick, GetTextLayoutResult]
   MergeDescendants = 'true'

Se você precisar fazer a correspondência de um nó do que seria a árvore não mesclada, defina useUnmergedTree como true:

composeTestRule.onRoot(useUnmergedTree = true).printToLog("TAG")

Esse código gera a seguinte saída:

Node #1 at (...)px
 |-Node #2 at (...)px
   OnClick = '...'
   MergeDescendants = 'true'
    |-Node #3 at (...)px
    | Text = '[Hello]'
    |-Node #5 at (83.0, 86.0, 191.0, 135.0)px
      Text = '[World]'

O parâmetro useUnmergedTree está disponível em todos os finders. Por exemplo, aqui ele é usado em um localizador onNodeWithText.

composeTestRule
    .onNodeWithText("World", useUnmergedTree = true).assertIsDisplayed()

Declarações

Verifique as declarações chamando assert() no SemanticsNodeInteraction retornado por um localizador com um ou vários correspondentes:

// Single matcher:
composeTestRule
    .onNode(matcher)
    .assert(hasText("Button")) // hasText is a SemanticsMatcher

// Multiple matchers can use and / or
composeTestRule
    .onNode(matcher).assert(hasText("Button") or hasText("Button2"))

Também é possível usar funções de conveniência para as declarações mais comuns, como assertExists, assertIsDisplayed e assertTextEquals. Confira a lista completa na página de referência de testes do Compose.

Também há funções para verificar declarações em uma coleção de nós:

// Check number of matched nodes
composeTestRule
    .onAllNodesWithContentDescription("Beatle").assertCountEquals(4)
// At least one matches
composeTestRule
    .onAllNodesWithContentDescription("Beatle").assertAny(hasTestTag("Drummer"))
// All of them match
composeTestRule
    .onAllNodesWithContentDescription("Beatle").assertAll(hasClickAction())

Ações

Para injetar uma ação em um nó, chame uma função perform…():

composeTestRule.onNode(...).performClick()

Veja alguns exemplos de ações:

performClick(),
performSemanticsAction(key),
performKeyPress(keyEvent),
performGesture { swipeLeft() }

A lista completa pode ser encontrada na Folha de referência de testes no Compose.

Matchers

Há uma variedade de correspondentes disponíveis para testar seu código do Compose.

Matchers hierárquicos

Os correspondentes hierárquicos permitem que você suba ou desça na árvore semântica e realize a correspondência.

fun hasParent(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnySibling(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnyAncestor(matcher: SemanticsMatcher): SemanticsMatcher
fun hasAnyDescendant(matcher: SemanticsMatcher):  SemanticsMatcher

Veja alguns exemplos desses matchers em uso:

composeTestRule.onNode(hasParent(hasText("Button")))
    .assertIsDisplayed()

Seletores

Uma forma alternativa de criar testes é usar seletores, que podem tornar alguns testes mais legíveis.

composeTestRule.onNode(hasTestTag("Players"))
    .onChildren()
    .filter(hasClickAction())
    .assertCountEquals(4)
    .onFirst()
    .assert(hasText("John"))

Confira a lista completa na página de referência de testes do Compose.

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.