Como lidar com a complexidade dos Testes Unitários?
Thiago Brito
28 de Janeiro de 2019 4 minutos de leitura

A complexidade de qualquer código tende a aumentar ao longo do tempo. Entropia de software é a capacidade do mesmo ficar caótico ao longo das suas alterações. Ivar Jacobson et al faz uma boa descrição do que seria isso:

A segunda lei da termodinamica, em princípio, diz que a desordem de um sistema não pode ser reduzida, podendo apenas ser mantida ou aumentada. A medida desta desordem é chamada entropia. Esta lei também é plausível para software; quando o sistema é modificado, sua desordem, ou entropia, sempre crescerá.

Um dos grandes fatores de qualidade do código são os Testes Unitários. Sendo eles parte importante do software que está sendo produzido, sua entropia tende a crescer junto com o código.

Alguns sinais encontrados nos Testes Unitários de que a entropia está alta e como resolver?

Demora

A alta dependência dos Testes Unitários com bancos de dados, requisições externas, ou uso desperdício de recursos faz com que os testes demorem o suficiente para que o desenvolvedor fique entediado e vá fazer outra coisa (YouTube, Globo.com, fumar etc.), desta forma o estado de flow nunca é alcançado reduzindo significativamente a produtividade. Além de perder tempo danado fazendo nada, só esperando os testes executarem.

O que fazer: Investigar o motivo da lentidão e implementar mocks quando necessário, reduzir número de dependencias das classes, respeitar o princípio da responsabilidade única.

Vale também considerar que estes são, na verdade Testes de Integração, sendo assim, talvez seja interessante mover para um outro lugar gerenciando os testes como tal. Talvez executando a bateria com menor frequência ou em um banco de dados mais simples e mais acessível.

Instabilidade

Os Testes Unitários devem ser confiáveis, quando algo quebra é que realmente existe um problema que precisa ser resolvido. O fato dos testes estarem instáveis, além de trazer problemas de produtividade, mascaram os reais problemas que podem vir a acontecer.

O que fazer: Se um teste está instável a ponto de ter se tornado “normal” quebrar no dia-a-dia, considere sériamente em remover estes testes da sua base. Se a quebra fosse algo realmente importante, ela já teria sido resolvida de alguma maneira.

Baixa cobertura de código

Uma das ferramentas para analisar quais pontos no código executados e quais não estão é chamada de Test Coverage, ou Cobertura de Código.

Importante: Uma armadilha muito comum é medir a cobertura de código como uma métrica de qualidade. Na verdade, esta é uma excelente ferramenta para entender onde devem ser adicionados novos testes.

Ter cobertura de 100% do seu código através dos Testes Unitários, pode não ser necessariamente algo bom. É mais importante que os testes validem as regras de negócio do código e indiquem falhas quando elas forem alteradas.

O que fazer: Utilize uma ferramenta para identificar onde o seu código não está sendo executado pelos Testes Unitários e use esta informação para mapear os pontos de melhoria dos seus testes.

Dificuldade em criar novos Testes Unitários

Um sintoma muito comum quando a entropia está nas alturas é a dificuldade de criar novos testes que analisam uma pequena porção de código.

Quando a arquitetura não está bem definida, existe grande dependencia entre os objetos ou até mesmo o princípio da responsabilidade única não foi respeitada a tendencia é que os Testes Unitários precisem de diversos outros objetos que tem suas dependencias (que precisam de outros objetos e… urgh!)

O que fazer: Este livro traz excelentes técnicas para trabalhar de forma mais efetiva com este tipo de código.

Tente isolar ao máximo as suas mudanças, reduzir o escopo dos seus objetos e simplificar ao máximo seu código como um todo. Somente assim, será possível bypassar as dependencias infinitas e reduzir a dificuldade ao criar novos testes.

Casos de Testes com muitos asserts

É tentador, você cria um caso de teste e coloca um assert, mas depois descobre que existe outra situação, bem parecida com a anterior, que vale a pena ser testada também. Criar um outro caso de teste? Claro que não? Vamos colocar um assert neste teste mesmo e pronto.

E a sementinha do mal é criada. Enquanto tudo está funcionando OK, seus Unit Tests passam sem problemas, está tudo bem. Porém, quando um caso de teste com diversos asserts quebra, a dificuldade em entender o que está se passando e sair desta cilada…. ahhh, isso pode trazer problemas.

O que fazer: Reduza ao máximo o código que você cria dentro de um caso de teste. Eu particularmente limito a 2 asserts por caso de teste e separo todo código que é comum aos outros testes em funções bem definidas.

Lembre-se, quanto mais código maior a entropia. Código duplicado não ajuda ninguém.

Infelizmente não existe uma métrica mágica para medir a entropia do código, o que pode ser analisado é o tempo que é levado para corrigir um bug, quantos bugs são criados a partir de alguma alteração, mapear a cobertura de código entre outras coisas, etc..

O que deve ser feito é limpar a casa constantemente, pequenos refactorings e deixar o código um pouco melhor a cada iteração. Desta forma, ao longo do tempo as coisas vão ficando mais fáceis e menos caóticas.