Esta página descreve os princípios básicos de teste de apps Android, incluindo as práticas recomendadas centrais e os benefícios deles.
Benefícios dos testes
Os testes são uma parte importante do processo de desenvolvimento de apps. Executando testes no app de forma consistente, você pode verificar a precisão, o comportamento funcional e a usabilidade dele antes de o lançar publicamente.
É possível testar manualmente o app navegando por ele. Você pode usar diferentes dispositivos e emuladores, mudar o idioma do sistema e tentar gerar os erros do usuário ou percorrer todos os fluxos do usuário.
No entanto, o teste manual não é bem dimensionado, e é fácil ignorar regressões no comportamento do app. Os testes automatizados envolvem o uso de ferramentas que realizam testes para você, que são mais rápidos, mais repetíveis e geralmente oferecem feedback mais útil sobre o app no início do processo de desenvolvimento.
Tipos de testes no Android
Os aplicativos para dispositivos móveis são complexos e precisam funcionar bem em vários ambientes. Dessa forma, há muitos tipos de testes.
Assunto
Por exemplo, há diferentes tipos de teste dependendo do assunto:
- Teste funcional: meu app faz o que deveria?
- Teste de desempenho: ele é rápido e eficiente?
- Teste de acessibilidade: o app funciona bem com os serviços de acessibilidade?
- Teste de compatibilidade: o aplicativo funciona bem em todos os dispositivos e níveis de API?
Escopo
Os testes também variam de acordo com o tamanho ou o grau de isolamento:
- Testes de unidade ou pequenos testes verificam apenas uma parte muito pequena do app, como um método ou uma classe.
- Testes completos ou grandes verificam partes maiores do app ao mesmo tempo, como uma tela inteira ou um fluxo do usuário.
- Os testes médios ficam no meio e verificam a integração entre duas ou mais unidades.
Há muitas maneiras de classificar testes. No entanto, a distinção mais importante para os desenvolvedores de apps é onde os testes são executados.
Testes instrumentados e locais
É possível executar testes em um dispositivo Android ou em outro computador:
- Os testes instrumentados são executados em um dispositivo Android, físico ou emulado. O app é criado e instalado junto com um app de teste que injeta comandos e lê o estado. Os testes instrumentados geralmente são testes de interface que iniciam um app e interagem com ele.
- Os testes locais são executados na máquina de desenvolvimento ou em um servidor e, por isso, também são chamados de testes do lado do host. Eles geralmente são pequenos e rápidos, isolando o assunto em teste do restante do app.
Nem todos os testes de unidade são locais e nem todos os testes completos são executados em um dispositivo. Por exemplo:
- Teste local grande: é possível usar um simulador do Android executado localmente, como o Robolectric.
- Pequeno teste instrumentado: verifique se o código funciona bem com um recurso do framework, como um banco de dados SQLite. Você pode executar esse teste em vários dispositivos para verificar a integração com várias versões do SQLite.
Exemplos
Os snippets abaixo demonstram como interagir com a interface em um teste de interface instrumentado que clica em um elemento e verifica se outro é mostrado.
Espresso
// When the Continue button is clicked
onView(withText("Continue"))
.perform(click())
// Then the Welcome screen is displayed
onView(withText("Welcome"))
.check(matches(isDisplayed()))
IU do Compose
// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()
// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()
Este snippet mostra parte de um teste de unidade para um ViewModel (teste local do lado do host):
// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)
// When data is loaded
viewModel.loadData()
// Then it should be exposing data
assertTrue(viewModel.data != null)
Arquitetura testável
Com uma arquitetura de app testável, o código segue uma estrutura que permite testar facilmente diferentes partes dele de forma isolada. As arquiteturas testáveis têm outras vantagens, como melhor legibilidade, facilidade de manutenção, escalonabilidade e reutilização.
Uma arquitetura não testável produz o seguinte:
- Testes maiores, mais lentos e instáveis. As classes que não podem ser testadas em unidades podem precisar ser cobertas por testes de integração ou de interface maiores.
- Menos oportunidades para testar cenários diferentes. Testes maiores são mais lentos. Por isso, testar todos os estados possíveis de um app pode ser inviável.
Para saber mais sobre as diretrizes de arquitetura, consulte o guia para arquitetura de apps.
Abordagens para o desacoplamento
Se você puder extrair parte de uma função, classe ou módulo do restante, o teste será mais fácil e eficaz. Essa prática é conhecida como desacoplamento e é o conceito mais importante para arquitetura testável.
Técnicas de desacoplamento comuns incluem:
- Divida um app em camadas, como apresentação, domínio e dados. Você também pode dividir um app em módulos, um por recurso.
- Evite adicionar lógica a entidades com dependências grandes, como atividades e fragmentos. Use essas classes como pontos de entrada para o framework e mova a lógica de negócios e de interface para outro lugar, como uma camada combinável, ViewModel ou de domínio.
- Evite dependências de framework diretas em classes que contêm lógica de negócios. Por exemplo, não use contextos do Android em ViewModels.
- Facilite a substituição de dependências. Por exemplo, use interfaces em vez de implementações concretas. Use a injeção de dependência mesmo que você não use um framework de DI.
Próximas etapas
Agora que você sabe por que testar e os dois principais tipos de teste, leia O que testar ou saiba mais sobre Estratégias de teste.
Se você quiser criar seu primeiro teste e aprender na prática, confira os codelabs de teste.