Espresso é um framework para testes de UI automatizados de aplicativos Android, desenvolvido pela equipe do Google e integrante do AndroidX Test. Diferente dos testes instrumentados que verificam componentes isolados, o Espresso interage com a UI real: clica em botões, insere texto e verifica a exibição de elementos. De acordo com Google Android Developers, o Espresso oferece sincronização automática com a thread de UI, eliminando a necessidade de Thread.sleep() manual.
Principais pontos
Espresso é uma biblioteca para escrever testes de UI automatizados para Android, parte do Google AndroidX Test. Ela fornece uma API para encontrar elementos View na tela, realizar ações neles (clique, entrada, swipe) e verificar seu estado (exibido, contém texto, habilitado).
A principal característica do Espresso é a sincronização automática com a thread principal do aplicativo. O framework aguarda a conclusão de todas as tarefas assíncronas (corrotinas, AsyncTask, Handler) antes de executar a próxima verificação. Isso elimina testes instáveis causados por condições de corrida e torna os testes de UI estáveis e confiáveis — nenhum teste contém Thread.sleep() ou loops de espera.
Espresso segue o princípio do Cachorro de Três Pernas — um teste consiste em três etapas: encontrar um elemento (ViewMatcher), realizar uma ação (ViewAction), verificar o resultado (ViewAssertion). As três etapas são escritas em uma cadeia de chamadas: onView().perform().check(). Esse conceito torna os testes previsíveis e fáceis de ler — cada teste descreve explicitamente o que procura, o que faz e o que verifica.
Arquitetura do Espresso é baseada em três componentes: Espresso (ponto de entrada — métodos estáticos onView e onData), ViewMatchers (busca de elementos), ViewActions (ações) e ViewAssertions (verificações). Internamente, o framework usa Idling Resource para sincronização com a thread de UI.
O teste mais simples encontra um botão por ID, realiza um clique e verifica se o texto “Concluído” aparece. Todas as operações são síncronas do ponto de vista do teste — o Espresso garante que a thread de UI terminou de processar o evento antes que o teste continue. Isso é alcançado por meio de um mecanismo de espera interno: onView bloqueia a execução do teste até que a UI fique inativa.
@Test
fun buttonClick_showsSuccessText() {
// Encontrar botão por ID e clicar
onView(withId(R.id.button_submit))
.perform(click())
// Verificar que o texto “Concluído” é exibido
onView(withText("Concluído"))
.check(matches(isDisplayed()))
}
Para iniciar um teste Espresso, é usado ActivityScenario (AndroidX Test), que cria uma Activity em um estado específico — em execução, pausada ou destruída. O ActivityScenario permite testar o ciclo de vida da Activity além dos testes de UI puros. Por exemplo, você pode verificar se os dados são preservados ao girar a tela (recriação da Activity) e restaurados após a destruição.
ViewMatchers é um conjunto de métodos da classe Espresso.onView que permitem encontrar Views na tela por vários critérios: ID de recurso (R.id), texto, dica, elemento pai e hierarquia. Se um matcher não produzir um resultado único, os matchers podem ser combinados usando allOf().
| Matcher | Finalidade |
|---|---|
| withId(R.id.name) | Busca por ID de recurso |
| withText(“texto”) | Busca pelo texto exibido |
| withHint(“dica”) | Busca pelo atributo hint do EditText |
| isDisplayed() | Verifica se o elemento está visível na tela |
| hasSibling(matcher) | Busca por elemento irmão |
| allOf(m1, m2) | Combinação de vários matchers |
Se houver vários elementos idênticos na tela (por exemplo, dois TextViews com textos diferentes), é conveniente combinar matchers usando allOf: onView(allOf(withId(R.id.title), withText(“Olá”))). Isso garante a seleção de um único elemento. O operador inverso — not() — exclui elementos da busca, e hasSibling() encontra um elemento próximo a um conhecido.
ViewActions são ações que o Espresso executa no View encontrado: click(), typeText(), clearText(), scrollTo(), swipeLeft() e outras. As ações são passadas para o método perform(), que pode aceitar várias ações em sequência.
O método perform() aceita vararg ViewAction, permitindo executar uma sequência de ações em um elemento: limpar o campo, inserir novo texto, fechar o teclado e clicar em um botão. Todas as ações são executadas na ordem em que são listadas, e o Espresso garante que a ação anterior seja concluída antes da próxima começar.
// Inserir texto no EditText e clicar no botão
onView(withId(R.id.edit_email))
.perform(
clearText(),
typeText("user@example.com"),
closeSoftKeyboard()
)
onView(withId(R.id.button_login))
.perform(click())
Para elementos dentro de AdapterView (ListView, RecyclerView), é usado o método onData() em vez de onView. Ele trabalha com dados do adaptador em vez de Views — encontra um elemento pelo conteúdo do modelo e retorna o View correspondente para ações posteriores. onData usa matchers hamcrest para localizar um elemento pelos campos de dados do modelo.
ViewAssertions verificam se um View está em um estado específico. O método básico — matches(matcher) — verifica se o elemento corresponde ao matcher fornecido. Além disso, o Espresso oferece doesNotExist() (elemento ausente) e selectedDescendantsMatch() (verificação de elementos aninhados).
As verificações mais frequentes em testes de UI: elemento está exibido (isDisplayed), elemento contém texto específico (withText), elemento está habilitado (isEnabled), elemento não está selecionado (isNotChecked). Cada verificação lança uma exceção detalhada em caso de falha — incluindo a hierarquia de Views na tela. Isso simplifica a depuração: a mensagem de erro mostra quais elementos estavam realmente na tela no momento da verificação.
Se as verificações padrão forem insuficientes, você pode criar uma personalizada através da interface ViewAssertion. Uma asserção personalizada recebe um View e pode verificar seu estado programaticamente — por exemplo, cor do texto, preenchimento ou o estado de um componente personalizado não exposto através de matchers padrão.
// Verificar: TextView é exibido e contém texto
onView(withId(R.id.text_welcome))
.check(matches(isDisplayed()))
.check(matches(withText("Bem-vindo")))
// Verificar: elemento NÃO é exibido
onView(withId(R.id.progress_bar))
.check(doesNotExist())
Idling Resource é o mecanismo do Espresso para sincronizar o teste com operações assíncronas. Por padrão, o Espresso aguarda Handler, AsyncTask e corrotinas (via coroutinesIdlingResource). Se o aplicativo realizar trabalho em segundo plano através de threads personalizadas ou serviços de callback, é necessário registrar um Idling Resource personalizado.
A partir do AndroidX Test 1.4.0, o Espresso suporta corrotinas via CoroutinesIdlingResource. O teste aguarda automaticamente todas as corrotinas lançadas antes de realizar verificações de UI. Para cenários mais complexos, é usado CountingIdlingResource — um contador que incrementa ao iniciar uma tarefa e decrementa ao concluí-la.
// Registrar IdlingResource para OkHttp
class OkHttpIdlingResource(
private val client: OkHttpClient
) : IdlingResource {
private var isIdle = true
private var watcher: IdlingResource.ResourceCallback? = null
override fun getName() = "OkHttp"
override fun isIdleNow() = isIdle
override fun registerIdleTransitionCallback(
callback: IdlingResource.ResourceCallback
) {
watcher = callback
}
}
Integração do Espresso em um projeto Android é feita adicionando dependências ao build.gradle do módulo. O Espresso faz parte do AndroidX Test, portanto basta especificar as dependências para o núcleo do Espresso, extensões e integração com JUnit. Os testes são colocados no diretório src/androidTest e executados em um dispositivo físico ou emulador via AndroidJUnitRunner.
O conjunto mínimo de dependências inclui espresso-core (núcleo), espresso-contrib (matchers adicionais para RecyclerView, Drawer, Picker) e runner (executor de testes AndroidX). Todos os testes são executados em um emulador ou dispositivo físico via Android Test Orchestrator.
// build.gradle.kts (dependências androidTest)
android {
defaultConfig {
testInstrumentationRunner =
"androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
androidTestImplementation("androidx.test.espresso:espresso-contrib:3.6.1")
androidTestImplementation("androidx.test:runner:1.6.1")
androidTestImplementation("androidx.test:rules:1.6.1")
}
Os testes do Espresso podem ser executados via Google Android Test Orchestrator, que isola cada teste em um processo separado e limpa o estado entre as execuções. Isso elimina testes instáveis causados por dados residuais de testes anteriores e melhora a estabilidade em servidores CI. Para execução paralela, é usado sharding — distribuição de testes entre vários emuladores.
Perguntas frequentes
Espresso funciona dentro do processo do aplicativo e usa sincronização automática com a thread de UI. O UI Automator funciona no nível do sistema, pode interagir com outros aplicativos, mas requer gerenciamento manual de espera.
É uma metáfora de uma apresentação do Google: um teste Espresso se apoia em três pilares — ViewMatcher (procurar), ViewAction (agir) e ViewAssertion (verificar). Remover qualquer um deles torna o teste instável, como um cachorro de três pernas.
Para RecyclerView, utiliza-se a biblioteca espresso-contrib e métodos como onView(withId(R.id.recycler)).perform(actionOnItemAtPosition(0, click())). Uma alternativa é onData() para AdapterView ou um ViewAction personalizado para encontrar um elemento por texto dentro do RecyclerView. Além disso, RecyclerViewActions do espresso-contrib pode ser usado para rolar até um elemento e realizar ações sobre ele.
Um teste instável é um teste que às vezes falha sem alterações no código, devido a condições de corrida ou assincronicidade. O Espresso resolve esse problema usando Idling Resource — aguardando a conclusão de todas as tarefas em segundo plano antes de realizar verificações.
O Espresso em si não foi projetado para testes de captura de tela, mas pode ser combinado com bibliotecas como Shot ou Paparazzi. O Espresso prepara a UI no estado desejado, e a biblioteca de comparação faz uma captura de tela e a compara com uma referência. Essa abordagem é chamada de teste de regressão visual e ajuda a encontrar alterações inesperadas na interface.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também