Ilustração de um semáforo de trânsito com um "$" na luz verde acesa.

Economia dos Testes

No mundo dos testes automatizados, os testes são classificados por níveis de validação. Testes que validam uma pequena unidade de código são chamados de testes unitários (unit tests). Quando validam a integração entre componentes, são chamados de testes de integração (integration tests).

Esses dois tipos de testes são os mais comuns. No entanto, também existem testes que simulam a interação real do usuário com a aplicação, conhecidos como testes end-to-end.

Cada tipo de teste gera custos de desenvolvimento, manutenção e execução ao longo da vida de um sistema. Em linhas gerais, quanto mais simples e pequeno um teste, mais barato é escrevê-lo e mantê-lo. Por exemplo, testes unitários são mais baratos que testes de integração.

O tempo de execução dos testes varia e isso também influencia no custo dele. Testes unitários são rápidos, enquanto testes funcionais ou end-to-end demoram mais devido à etapa de preparação que costuma ser bem longa.

Testes bem escritos custam mais para serem desenvolvidos, mas reduzem os custos de manutenção. O oposto também é verdade: testes mal escritos podem até ser mais baratos para serem escritos, mas custam caro para serem mantidos.

Os testes unitários são fáceis de escrever e manter se o código estiver bem desacoplado, pois testam apenas uma pequena unidade de código. Testes de integração, embora mais caros, garantem que a comunicação entre partes do sistema funcione corretamente sem que o tempo de execução aumente.

Com os testes funcionais ou testes end-to-end avaliam a capacidade do software de resolver problemas reais. Como o nome diz eles testam se o software “funciona”. Embora desejáveis, são difíceis de escrever corretamente e são os mais caros de desenvolver, manter e executar.

Entendendo a relação entre o custo e os benefícios que cada tipo de teste trás, como distribuir o “orçamento” que você tem para escrever testes?

Minha estratégia

Minha estratégia favorita é escrever muitos testes unitários, alcançando alta cobertura.

Exemplo: 235 passed in 100s; 99.98% coverage

Também escrevo testes de integração para cenários ideais (happy path) e de falhas esperadas.

Exemplo:

  1. Teste acessar perfil público do usuário @publico
  2. Teste falha ao acessar perfil privado do usuário @privado
  3. Teste falha ao acessar qualquer perfil sem autenticação

Não faria um teste de integração para “Falha ao acessar um usuário com nome inválido” porque um teste unitário já deveria garantir isso. Se a regra mudar, não preciso alterar testes em vários lugares.

Para os testes funcionais ou end-to-end, foco nos fluxos fundamentais do sistema.

Exemplo:

  1. Fluxo de Cadastro (sign up): se esse fluxo quebrar, novos clientes não serão convertidos.
  2. Fluxo de Registro (sign in): se esse fluxo quebrar, clientes não conseguirão usar o produto.
  3. Fluxo de Compra (check out): se esse fluxo quebrar, em um e-commerce, não venderíamos.

Ou seja, escrevo testes funcionais ou end-to-end apenas para garantir que, se algo falhar, a aplicação não se torne completamente inútil.


Comentários

O espaço abaixo é todo seu…