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 IU 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 em teste 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 o Compose.
Essa API é muito semelhante aos Recursos de inatividade do Espresso, usados para indicar se
o assunto em teste está inativo ou ocupado. Use a regra de teste do Compose para registrar
a implementação do 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 o carregamento de dados ou
a medição ou o desenho do Android (ou seja, medição ou desenho externos ao Compose), precisa usar um
conceito mais geral, como waitUntil()
:
composeTestRule.waitUntil(timeoutMs) { condition }
Também é possível usar qualquer um dos
ajudantes 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 inicial 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 principais conceitos por trás dos testes de um app Android.
- Testes locais:é possível executar alguns testes localmente na sua estação de trabalho.
- Testes instrumentados:é uma boa prática também executar testes instrumentados. 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 alguns dispositivos disponíveis para os usuários, é necessário 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.