fbpx

Teste difícil de escrever diz muito sobre seu código

O teste difícil de escrever diz muito sobre seu código

Neste artigo vou falar de como os testes unitários podem ajudar a identificar problemas de design em seu código e de algumas medidas que podem ser tomadas logo que são identificados.

O bom e velho legado

Não é fácil testar código acoplado e sem coesão.

Nas últimas semanas, trabalhei no código legado de um dos serviços que meu time ajuda a manter aqui na empresa. O código estava muito ruim de entender; muitas classes acopladas, sem responsabilidade bem definida, regras de negócio resolvidas em consultas, zero de cobertura de testes. Sempre que precisávamos mudar alguma coisa era um parto.

O objetivo da mudança foi para resolver um problema de performance de um serviço que recebe um grande volume de requisições. A grosso modo, o serviço funciona como se fosse o windows update de terminais de pagamento. É através dele que milhares de POS recebem novas versões de aplicativos.

O sistema resolve regras de negócio complexas que precisam controlar versões de aplicativos instalados, controle de sessão de download e servir pacotes de arquivos fragmentados.

Estávamos começando a ter problemas de performance por causa de consultas pesadas. Então, decidimos que seria impossível continuar evoluindo o sistema, sem antes que antes resolvêssemos alguns débitos técnicos.

Acoplamento

O ponta pé inicial foi a decisão de escrever teste unitário para cada método público que precisasse ser alterado. Da forma que estava, sem testes e diversas regras de negócio resolvidas em consulta, seria impossível prosseguir.

Não foi fácil mapear e isolar regras de consultas, isolar as dependências; quanto mais eu aprofundava nos métodos, mais dependências eu descobria.

O conceito de acoplamento diz respeito ao grau de conhecimento que um componente possui a respeito de outros componente do sistema ao qual se integra. Esse componente pode ser uma classe, método ou qualquer outro código reutilizável dentro do sistema.

Quanto menor for o grau de acoplamento, maior será a autonomia e controle, pois do ponto de vista externo, quem consome o componente, o visualiza como uma caixa preta, somente atribuindo valores a sua entrada e esperando pela sua saída.

Em contrapartida, quanto mais alto for o grau de acoplamento, maior é a dificuldade em funcionar isoladamente. Consequentemente, pior é efetuar testes daquela unidade de código, pois não é tarefa simples simular as entradas desejadas em busca das asserções que garantem as saídas esperadas, e também o funcionamento correto do que estiver sendo implementado.

Após mapear e isolar as dependências do método, o segundo passo foi expô-las para poder injetar objetos que simulassem o comportamento de acordo com os cenários que precisei testar.

Depois da exposição das dependências, ficou mais fácil testar os métodos separadamente.
Isolando completamente as dependências que não importavam para os cenários de teste, foi tarefa simples fazer asserções sobre as regras que estavam sendo testadas.

Coesão

Outra dificuldade foi em montar os cenários de teste para cada regra que precisei validar.

Classes com muitas responsabilidades são difíceis de ser mantidas. Por outro lado, classes com poucas responsabilidades são mais fáceis de ser evoluídas.

Uma classe coesa é justamente aquela que possui uma única responsabilidade.
Em sistemas orientados a objetos, a ideia é sempre buscar por classes coesas, e quando o código começa a apresentar esses problemas, é o teste unitário que dispara o primeiro tiro de alerta.

Ao som do disparo, alguns indícios que podem indicar que seu código está com problemas de coesão:

  • Muitos testes para um método;
  • Muitos testes para uma classe;
  • Cenário muito grande, ou seja, você precisa lidar com muitos objetos para testar o cenário;
  • Necessidade de testar um método privado;
  • Muitas dependências.


À medida que fui encontrando dificuldade para testar os métodos, comecei a quebrar em classes menores, coesas e especialistas em um único assunto. As novas classes que nasceram ficaram mais fáceis de testar. Quanto mais eu quebrava em classes menores, mais sentido elas faziam com relação ao todo.

Sempre que se deparar com código que faz você perder tempo tentando encontrar um jeito de testá-lo, é melhor correr para remodelá-lo. Se isso não for feito, é muito provável que ele se vire contra você no futuro.

Receba meu conteúdo no Telegram

Se você deseja receber outros conteúdos direto no seu celular, entre no meu canal no Telegram.
Lá eu compartilho dicas para você dominar definitivamente a escrita do código limpo.

Hey,

o que você achou deste conteúdo? Conte nos comentários.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *