Estratégia de Testes no Android: Piramide e Cobertura de testes — Parte 2

Natan Ximenes
6 min readMar 1, 2022
Photo by Gaurav D Lathiya on Unsplash

Se você ouviu falar sobre a Pirâmides de Testes, é muito provável que você já tenha associado-a ou confundido-a como uma Estratégia de Testes.

É absolutamente normal estudar sobre testes, conhecer a Piramide de Testes e aplica-la como uma regra, ao invés de utiliza-la apenas como uma ferramenta guia.

No meu primeiro post, explico o que de fato é uma estratégia de testes, se não leu, corre la!

De forma breve, uma Pirâmide de Teste demonstra uma distribuição ideal de tipos de teste, para uma aplicação, considerando tempo de execução e manutenibilidade, seguindo o esquema:
70% Unitarios20% Integração10% UI, somando 100%.

Assim, num projeto de um app Android poderíamos aplicar a Pirâmide de Testes, onde testaríamos bastante as nossas unidades, testariamos, de forma ponderada, a comunicação das unidades de forma integrada e validaríamos nossa UI, de forma pontual.

Entretanto, uma suite de testes não precisa ter necessariamente esse formato geométrico. Pense em libs como Room, Retrofit, Koin, Coroutines, RxJava… todas elas são libs utilizadas por apps Android, entretanto, nenhuma delas provê nada relacionado a renderização de UI.

Ou seja, a nossa Piramide, ja perderia o formato, por conta do topo(Testes de UI) não se aplicar a esses tipos de projeto. Ficaria (não necessariamente) como na imagem ao lado, restando apenas Testes unitários e Testes integrados.

Ou seja, a pirâmide nos mostra apenas um esquema de distribuição de uma suite de testes, baseada numa correlação entre tempo de execução e manutenibilidade de um projeto que envolva um front-end. Ela não nos diz muito mais além disso.

O problema de leva-la como um padrão, é que não necessariamente uma suite de testes precisa estar distribuída seguindo essa proporção. Neste artigo aqui, você pode ver uma distribuição de testes diferente, utilizando o Testing Trophy.

Por exemplo:

Há aplicações inteiras, ou parte de uma aplicação, que são simples “espelhos” do que uma API responde. Apenas exibem, na tela, o que o backend retorna. Não há lógicas a serem válidas, não há tratamento de dados.

Nesses cenários, o que valeria mais a pena, ter testes unitarios repetitivos, de classes que são meros proxies(uma classe chamando e passando o retorno para a outra, sem nenhuma lógica), ou ter testes de integração que validam o retorno de um conjunto de classes que tem o mesmo objetivo?

A resposta é simples: depende.

Depende do que o time considera importante(tempo, manutenibilidade, custo de execução, etc..) e também depende da perspectiva de evolução daquela aplicação ou daquela parte específica.

Nem sempre uma estratégia de testes vai se manter igual ao longo da evolução do produto. Tudo muda ao longo do tempo: mercado, requisitos, usuários, ferramentas, tecnologias e etc. A estratégia de testes precisa evoluir junto.

A única resposta certa é que uma Pirâmide de Testes não te diz isso, justamente porque ela não representa uma estratégia, ela é apenas um guia do que podemos fazer para distribuir testes.

Ela nos diz o que testar, mas não nos diz como testar, não leva em consideração as questões relacionadas a particularidades de um software, nem as questões relacionadas a sincronização de conhecimento entre um time e principalmente não serve como base para olhar os principais pontos de falha de uma aplicação… se olharmos para ela como um simples ideal de cobertura de testes.

Noah Sussman propôs uma nova forma de enxergar a Piramide de Testes, utilizando-a como um Filtro de Bugs. Pode parecer que é a mesma coisa, só que virada para baixo.

https://twitter.com/noahsussman/status/836612175707930625/photo/1

Isso traz mais propósito à pirâmide de teste, já que ela deixa de ser apenas uma proposta de distribuição geométrica de testes. A Pirâmide de Teste de Noah torna mais fácil decidir qual é o melhor teste para um problema específico que pode acontecer.

Assim, ao olhar para a nossa suite de testes, com um ideal de propósito ao invés de um ideal de cobertura de testes, há uma tendência maior a criar testes com objetivos mais claros, que geram valor de fato.

A cobertura de testes apenas expressa quais linha de código, de uma ou mais classes, estão sendo executadas em tempo de teste.

Isso pode ser visto nesse exemplo abaixo.

Temos uma classe que realiza validações de nomes. Nela, existem algumas regras, que retornarão um valor booleano, que indicará se uma string contém um nome válido ou não.

Abaixo, temos seus testes unitarios:

Se executarmos alguma ferramenta de cobertura de testes, como o jacoco, nos seria informado que a classe NameValidator tem 100% de cobertura de testes. “Isso quer dizer que atingimos qualidade, certo?” Não exatamente.

Repare que essa validação de nomes não está completa. Se nós passarmos as seguintes Strings para o NameValidator, ela retornaria true:
“123”, “Joãozinho#1992”, “Gol do Brasil aos 45 do 2º tempo”, “😁Messi do PSG😎”

Ou seja, estaríamos passando strings com numeros, caracteres especiais e etc, como se fossem nomes, e o nosso NameValidator retornaria true, como se fossem nomes válidos de verdade para uma pessoa.

Nessa classe, faltam validações para numeros e caracteres inválidos, para de fato garantir que um nome é valido ou não. Mesmo assim, o relatório de cobertura de testes diria que está classe está 100% coberta.

Isso exemplifica porque cobertura de testes não necessariamente expressa qualidade.

E é por isso que olhar para a Pirâmide de Testes proposta por Noah Sussman(ou qualquer outro guia de distribuição geométrico de testes), como um Filtro de Bugs, nos ajuda a pensar um pouco mais em casos de testes e pontos de falha, do que simplesmente em cobertura.
É tudo uma questão de perspectiva.

Falei aqui bastante sobre algumas definições sobre Pirâmides de Testes e Cobertura de Testes, mas de forma teórica.

Se você quiser ver na prática, com funciona essa divisão de Pirâmide, pode dar uma olhada nessa série de posts do Phellipe Silva, que começa aqui:

Se você quiser ver na prática, como gerar um relatório de cobertura de testes, pode dar uma olhada nesse post do Rafael Toledo:

Aqui uma lista dos conteúdos que eu consumi até hoje sobre teste, que serviram de referencia para este artigo?

Curtiu? Compartilha o post com quem está num momento de aprendizado/evolução sobre testes e comenta aí, caso você já tenha tido que criar uma estratégia de testes para validar sua aplicação !

--

--

Natan Ximenes

Senior Software Engineer, Android @ League, passionate about Android development, Agile and Digital products.