Desafios com testes

Concluído

Em projetos de software, testes podem ser complicados e ser muito difíceis. Quando projetos existentes não são criados com muitos testes, o código tende a ser complexo e menos robusto. Entender os problemas e possíveis armadilhas com testes é crucial para um projeto de software bem-sucedido.

Falta de testes

Quando projetos de software são construídos sem testes (ou um número inadequado de testes), o código pode se deteriorar, tornar-se frágil e difícil de entender. Os testes fazem com que o código seja responsável pelo próprio comportamento e, quando os testes são introduzidos, ele força os engenheiros a facilitar o teste do código.

Há alguns efeitos colaterais positivos do teste que você pode reconhecer em seu código. Funções e métodos escritos com o teste em mente tendem a:

  • Ter no máximo uma dezena de linhas.
  • Ter apenas uma responsabilidade, em vez de fazer muitas coisas diferentes.
  • Ter uma quantidade única ou mínima de entrada em vez de muitos argumentos e valores.

A entrada curta, de responsabilidade única e mínima torna o código mais fácil de entender, manter e testar. Quando testes não estão envolvidos, é comum ver funções menores crescerem em várias centenas de linhas, fazendo muitas coisas. O código evolui dessa maneira porque não há responsabilidade que impeça a complexidade desnecessária.

Código herdado

Uma maneira de pensar no código não testado é rotulá-lo como herdado. É comum encontrar código não testado em projetos de software. O código pode deixar de ser testado por diferentes motivos, como falta de experiência com testes ou práticas de desenvolvimento que não permitem tempo suficiente para considerar o teste como parte da produção de software.

Como já mencionado, uma característica do código não testado é que é difícil de compreender e muitas vezes pode ser bastante complexo pelo mesmo motivo. Um efeito colateral de todos esses problemas é que torna o código ainda mais difícil de lidar, fazendo com que a função (ou método) continue aumentando com mais lógica e caminhos de código mais entrelaçados.

Quanto menor a função, mais fácil será testar.

Testes lentos e não confiáveis

Embora um conjunto de testes existente seja ótimo para começar, pode ser problemático quando contém testes lentos ou não confiáveis. Um desenvolvedor estará mais propenso a executar testes com frequência se eles fornecerem comentários rápidos. Se um conjunto de testes levar horas para ser executado em vez de minutos (ou segundos), um desenvolvedor não poderá executá-lo com tanta frequência. Quando o loop de comentários está lento, o processo de desenvolvimento é comprometido.

Da mesma forma, você pode encontrar situações em que um teste pode falhar sem um motivo aparente. Testes não confiáveis às vezes são chamados de incertos. A principal responsabilidade de um conjunto de testes é demonstrar que o código em teste está atendendo às expectativas definidas pelos próprios testes. Se os testes não forem confiáveis, você não poderá realmente dizer se o código precisa ser alterado ou se um patch introduziu uma regressão.

Testes não confiáveis (ou incertos) devem ser corrigidos ou removidos do pacote. Nem todos os testes podem ser rápidos e alguns tipos de testes, como testes de integração, podem ser lentos. Mas ter um conjunto de testes sólido que fornece comentários rápidos é essencial.

Falta de automação

Quando os testes não acontecem de maneira automatizada, é fácil esquecer o que testar e há maior probabilidade de erros. Mesmo em pequenos projetos de software, é fácil esquecer se a alteração de uma condição em uma função pode ter um efeito colateral (negativo) em algum outro lugar da base de código. Quando um desenvolvedor de software não tem a tarefa de lembrar o que e quando testar porque tudo acontece automaticamente, a confiança no software, nos testes e no sistema geral aumenta.

A automação se trata de remover tarefas repetitivas e reduzir as etapas necessárias para que uma ação ocorra. Os testes automatizados podem acontecer quando o código é enviado para um repositório remoto ou mesmo antes de serem mesclados. Impedir que o código defeituoso entre no código de produção sem verificações manuais é fundamental para um aplicativo robusto.

Ferramentas de teste

Alguns dos desafios vêm da falta de testes, enquanto outros estão relacionados a experiências ruins de teste e não saber quais técnicas aplicar. Já mencionamos o código herdado neste módulo e como o código não testado pode continuar aumentando de tamanho e complexidade. As ferramentas de cobertura de teste podem informar com precisão quais caminhos de código são testados e quais não estão sendo cobertos por testes existentes.

Contar com ferramentas e bibliotecas de teste é uma ótima maneira de reduzir a quantidade de esforço necessária para produzir bons testes. Dependendo da linguagem e do aplicativo que está sendo testado, você deve encontrar soluções que possam tornar os testes mais fáceis e robustos.

Aqui estão alguns exemplos sobre o que essas ferramentas devem ser:

  • Uma ferramenta de cobertura de teste para relatar caminhos de código testados e não testados.
  • Uma ferramenta de execução de testes, que pode coletar, executar e executar novamente testes específicos.
  • Um ambiente CI/CD, que pode executar testes automaticamente e evitar que código defeituoso seja mesclado ou implantado.