Criando testes confiáveis para notificações Android

Igor Escodro
Android Dev BR
Published in
4 min readMar 10, 2023

--

White lighthouse on rocky seashore

Notificações são uma parte muito importante dos aplicativos Android, mostrando informações relevantes, informando quando o usuário precisa tomar alguma ação e até mesmo não deixando-o perder compromissos importantes. Como esse aspecto é crítico para alguns apps, nada melhor do que adicionar testes para validar o comportamento.

Uma maneira de se testar notificações é criar uma interface independente de componentes Android para realizar testes unitários na estrutura e comportamento de uma notificação, mas sem realmente lançá-la. Apesar de ser uma boa maneira de testar, ela não cobre as particularidades do ecossistema Android, como “a notificação foi enviada no momento apropriado?”, “a notificação abriu a tela correta” e assim por diante.

Outra maneira de testá-las é usando o UiAutomator, que nos permite criar interações entre diferentes apps, permitindo abrir manualmente a barra de notificações e realizar uma série de ações para validar o comportamento. Em 2019, eu implementei alguns testes usando essa ferramenta, mas em 2022 decidi procurar uma outra alternativa por dois motivos:

  • Os testes falhavam com frequência (flaky) — em alguns momentos a notificação não estava visível na barra, o texto para “Limpar” as notificações pode variar dependendo da versão de Android e por aí vai
  • O UiAutomator está desatualizado — o último lançamento foi em 2018

Então como podemos criar testes mais confiáveis?

Usando o NotificationManager para testes

Sim, a resposta é mais fácil do que imaginávamos. Podemos usar o NotificationManager com Espresso ou Compose Tests para validar todos os comportamentos esperados. Vamos dar uma olhada em um teste simples usando essa ferramenta:

No código acima, nós lançamos uma notificação e usamos o NotificationManager para pegar a primeira notificação e validar que tanto o nome quanto o id conferem com a notificação enviada. O NotificationManager acessa apenas as notificações lançadas pelo nosso próprio app, então não tem problema se a barra tiver dezenas delas ou se a notificação do nosso app não estiver visível no topo.

Limpando as notificações

As notificações lançadas irão permanecer na barra se nenhuma ação for tomada. Logo, é uma boa prática limpar todas as notificações após a execução de cada teste para evitar conflito entre eles:

Simples assim.

Recursos de inatividade (Idling resources)

Uma vez que o código de teste roda muito rápido, é possível que entre a chamada do send() e o assert a notificação ainda não esteja disponível na lista do NotificationManager, o que irá falhar o teste. Para evitarmos isso, precisamos encontrar alguma forma de sincronizar o teste e o app. A página do Android Developers tem uma documentação em como usar os Recursos de inatividade do Espresso, e mais recentemente o Jose Alcérreca publicou um excelente artigo em alternativas para o Jetpack Compose.

No nosso exemplo, vamos assumir que as telas foram desenvolvidas usando Compose e ver como o waitUntil() pode nos ajudar aqui.

O código atualizado agora espera até a lista de notificações ativas não esteja vazia antes de fazer a validação. O padrão de espera é de 1 segundo, mas esse valor é customizável. Para saber mais sobre o waitUntil(), por favor acesse os documentos oficiais.

Testando ação de notificações

Intent da notificação

Agora que conseguimos testar títulos e conteúdos de uma notificação, o próximo passo é testar se as suas ações estão funcionando. Vamos imaginar que temos uma notificação que ao ser clicada mostra uma tela com mais informações. O código de teste seria assim:

No código acima, após lançar a notificação e pegá-la da lista de notificações, chamamos o contentIntent.send(). Esse comando irá pegar a PendingIntent e executá-la logo em seguida. Então podemos validar que a tela correta foi aberta.

Ação dos botões

No nosso próximo exemplo, vamos imaginar que temos uma notificação que informa que uma nova mensagem foi recebida pelo nosso app. E para uma interação mais rápida, nós temos um botão de “Marcar como lido” que atualiza o estado da mensagem e limpa a notificação. O código para esse comportamento seria assim:

Desta vez, após pegarmos a notificação, acessamos o primeiro Notification.Action da lista de actions e executamos a PendingIntent. Após isso validamos que a nossa mensagem está marcada como lida no nosso repositório e que a lista de notificações está vazia.

Conclusão

O NotificationManager nos permite ter mais controle sobre as notificações lançadas pelo nosso aplicativo, tornando mais fácil testar diferentes comportamentos e cenários. Na minha experiência pessoal, consegui criar testes de uma forma mais fácil e mais confiável do que utilizando o UiAutomator.

Próximos passos

Como sempre, eu adoraria compartilhar o Pull Request do meu app pessoal, o Alkaa — Tarefas simplificadas. Essa mudança adiciona vários testes instrumentados, inclusive de notificações.

Muito obrigado por ler o meu artigo! ❤️

--

--

Igor Escodro
Android Dev BR

Passionate Android developer | Google Developer Expert for Android