Por padrão, os testes do Compose são sincronizados com sua IU. Quando você chama uma
declaração ou uma ação com o ComposeTestRule
, o teste é sincronizado
antecipadamente enquanto aguarda até que a árvore da UI fique inativa.
Normalmente, não é necessário fazer nada. No entanto, existem alguns casos extremos que você precisa conhecer.
Quando um teste é sincronizado, o tempo do app Compose é avançado usando um relógio virtual. Isso significa que os testes do Compose não são executados em tempo real, para que possam ser realizados o mais rápido possível.
No entanto, caso você não use os métodos que sincronizam os testes, nenhuma recomposição vai ocorrer, e a IU aparentará estar pausada.
@Test
fun counterTest() {
val myCounter = mutableStateOf(0) // State that can cause recompositions.
var lastSeenValue = 0 // Used to track recompositions.
composeTestRule.setContent {
Text(myCounter.value.toString())
lastSeenValue = myCounter.value
}
myCounter.value = 1 // The state changes, but there is no recomposition.
// Fails because nothing triggered a recomposition.
assertTrue(lastSeenValue == 1)
// Passes because the assertion triggers recomposition.
composeTestRule.onNodeWithText("1").assertExists()
}
Esse requisito se aplica apenas a hierarquias do Compose e não ao restante do app.
Desativar a sincronização automática
Quando você chama uma declaração ou ação usando ComposeTestRule
, como
assertExists()
, seu teste é sincronizado com a IU do Compose. Em alguns casos,
pode ser necessário interromper essa sincronização e controlar o relógio. Por
exemplo, você pode controlar o tempo para fazer capturas de tela precisas de uma animação em um
ponto em que a IU ainda estaria ocupada. Para desativar a sincronização automática,
defina a propriedade autoAdvance
em mainClock
como false
:
composeTestRule.mainClock.autoAdvance = false
Normalmente, isso fará com que o tempo seja avançado. É possível avançar exatamente um
frame com advanceTimeByFrame()
ou um intervalo específico com
advanceTimeBy()
:
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
Recursos inativos
O Compose pode sincronizar testes e a IU para que todas as ações e declarações sejam executadas em estado inativo enquanto estão aguardando ou avançando o relógio conforme necessário. No entanto, algumas operações assíncronas com resultados que afetam o estado da IU podem ser executadas em segundo plano enquanto não afetam os testes.
Crie e registre esses recursos de inatividade no teste para que eles sejam considerados ao decidir se o app sendo testado está ocupado ou inativo. Não é necessário fazer nada, a menos que você precise registrar outros recursos de inatividade, por exemplo, executar um job em segundo plano que não esteja sincronizado com o Espresso ou Compose.
Essa API é muito semelhante aos Recursos de inatividade do Espresso, usados para indicar se o assunto sendo testado está inativo ou ocupado. Use a regra de teste do Compose para registrar
a implementação de IdlingResource
.
composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)
Sincronização manual
Em alguns casos, você precisa sincronizar a IU do Compose com outras partes do teste ou do app sendo testado.
A função waitForIdle()
aguarda que o Compose esteja inativo, mas depende da propriedade
autoAdvance
:
composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.
composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.
Em ambos os casos, waitForIdle()
também aguarda transmissões de layout e desenho pendentes.
Além disso, você pode avançar o relógio até que uma determinada condição seja atendida com
advanceTimeUntil()
.
composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }
A condição especificada precisa ser verificar o estado que pode ser afetado por esse relógio. Isso só funciona com estados no Compose.
Aguardar condições
Qualquer condição que dependa de trabalho externo, como carregamento de dados ou medidas ou desenhos do Android (ou seja, medidas ou desenhos externos ao Compose), precisa usar um conceito mais geral, como waitUntil()
:
composeTestRule.waitUntil(timeoutMs) { condition }
Também é possível usar qualquer um dos
assistentes waitUntil
:
composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)
composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)
composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)
composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)
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 principais conceitos 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:é uma boa prática executar também testes de instrumentação. Ou seja, testes executados diretamente no dispositivo.
- Integração contínua:permite 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 do teste do Compose.