Quase todo time que decide "levar testes a sério" começa pelo lugar errado: escolhendo a ferramenta. Discute-se framework, plugin, runner, e só depois alguém percebe que ninguém definiu o que, afinal, vai ser testado e como.
A ferramenta é a última decisão, não a primeira. Antes dela vêm escolhas estruturais que determinam se a sua suíte vai ser um ativo ou um peso morto. Quem define essas escolhas na ordem certa monta uma base que dura anos. Quem improvisa monta uma suíte que será reescrita em seis meses.
Este texto é um roteiro. Não é uma lista de "boas práticas" soltas, e sim a sequência de passos que eu sigo quando preciso estruturar a arquitetura de testes de um produto do zero.
Passo 1: defina o que é risco antes de definir o que testar
Testar tudo é impossível e desnecessário. A primeira decisão é entender onde está o risco real do produto.
Em um sistema de pagamento, o risco está no cálculo de valores e na idempotência das transações. Em um portal de serviços públicos, está na elegibilidade e no controle de acesso a dados pessoais. Em um e-commerce, está no carrinho e no checkout. Mapeie isso primeiro.
Esse mapa de risco define onde vale investir testes profundos e onde basta uma verificação leve. Sem ele, o time gasta energia testando o trivial e deixa o crítico descoberto, o pior dos mundos.
Passo 2: estabeleça os níveis e suas fronteiras
O segundo passo é decidir os níveis de teste e o que cada um cobre. A pirâmide clássica serve de guia: muitos testes de unidade, alguns de integração, poucos de ponta a ponta.
Mais importante que o formato é a fronteira de cada nível. Teste de unidade verifica uma regra isolada, sem infraestrutura. Teste de integração verifica se componentes ou serviços conversam corretamente. Teste de ponta a ponta exercita o fluxo do usuário inteiro.
Definir essas fronteiras com clareza evita o erro mais caro: testes que se sobrepõem. Quando o mesmo comportamento é verificado em três níveis, qualquer mudança quebra três testes, e a suíte fica frágil sem ganhar confiança.
Passo 3: garanta isolamento desde o primeiro teste
Isolamento é a propriedade que mais decide a saúde futura da suíte, e a que mais é negligenciada no começo.
Cada teste precisa montar seu próprio cenário e limpá-lo ao final. Nenhum teste pode depender do que outro deixou no banco, na memória ou no sistema de arquivos. No instante em que um teste assume que "o usuário X já existe", você plantou uma bomba-relógio.
A consequência prática é exigente: testes de unidade não tocam banco, rede nem relógio. Se a sua função só dá para testar subindo meia aplicação, o problema é o acoplamento do código. O teste está te dando um diagnóstico de arquitetura de graça.
Passo 4: decida como tratar dependências externas
Banco de dados, APIs de terceiros, gateways de pagamento, serviços de e-mail. Toda aplicação real depende de coisas fora dela. Como tratá-las nos testes é uma decisão estrutural.
Há dois extremos ruins. Mockar tudo deixa a suíte rápida mas mentirosa: você testa a sua suposição sobre a dependência, não a dependência. Usar tudo real deixa a suíte fiel mas lenta e instável.
O equilíbrio que defendo: dublês nas dependências internas e periféricas, integração real nas fronteiras críticas. O gateway de pagamento e a camada de persistência merecem testes contra implementações reais, em ambiente controlado. O serviço de e-mail, na maioria dos casos, pode ser simulado.
Passo 5: trate dados de teste como parte da arquitetura
Dados são a parte invisível que afunda suítes. Cenários montados na mão, espalhados, duplicados, viram um pesadelo de manutenção quando o modelo de dados muda.
Centralize a criação de cenários em construtores reutilizáveis. Em vez de cada teste montar um pedido completo do zero, ele pede "um pedido válido" e ajusta só o que importa para o caso. Isso reduz ruído, deixa o teste legível e protege a suíte de mudanças no modelo.
Em produtos que lidam com dados pessoais, há um cuidado extra que muitos esquecem: nunca use dados reais de produção em ambiente de teste. Além de risco de vazamento, isso esbarra direto na LGPD. Dados de teste devem ser sintéticos.
Passo 6: integre à esteira desde o início
Uma suíte que só roda na máquina de quem escreveu não protege ninguém. O sexto passo é integrar os testes ao CI desde o começo, não como retrofit.
Estruture em estágios: unidade primeiro, falha rápido; integração e ponta a ponta depois. Defina que um pull request não entra com a suíte vermelha. Essa regra simples muda a cultura, porque transforma o teste de "tarefa opcional" em parte do fluxo de entrega.
E meça o tempo de execução desde cedo. Uma suíte que cresce sem controle de tempo vira, mais cedo ou mais tarde, algo que o time aprende a contornar.
O passo que ninguém formaliza: manutenção
Há um passo final que raramente entra nos roteiros: decidir quem cuida da suíte ao longo do tempo. Código de teste envelhece, acumula duplicação e ganha testes intermitentes como qualquer sistema.
A decisão estrutural aqui é tratar teste como parte da definição de pronto e a saúde da suíte como métrica de engenharia. Sem dono e sem métrica, a melhor arquitetura inicial degrada em um ou dois anos.
Montar a arquitetura de testes na ordem certa, risco, níveis, isolamento, dependências, dados, esteira, manutenção, não é burocracia. É o que faz a diferença entre uma suíte que te dá coragem de evoluir o sistema e uma que te dá medo de tocá-lo.
Se você está estruturando testes em um produto novo ou tentando resgatar uma suíte que virou peso, vale começar por esses passos antes de abrir o editor. Tenho outros artigos no blog sobre qualidade e engenharia, e se isso é uma dor concreta no seu time, é uma boa conversa.
Leia também
- Arquitetura de testes automatizados: um guia rápido para times que precisam de velocidade
- Testes de regressão: o seguro contra quebrar o que já funcionava
- Testes automatizados: por que código sem teste é dívida
- Ciclo de testes de software: tendências e um guia rápido para líderes
- Performance de software: o que casos reais ensinam sobre qualidade
- Testes Automatizados: Arquitetura e Fundamentos