וּבְחָנוּנִי נָא בָּזֹאת uvchanuni na bazot · provai-me nisto · Malachi 3:10

Blog/Artigos · Engenharia

Testes automatizados: provai-me nisto, e mude o código sem medo

A pirâmide de testes, o ciclo red-green-refactor do TDD, a diferença entre cobertura e confiança, e o teste como pressão de design.

Por Juliano Vince de Campos · · 9 min de leitura · 5 seções · 5 figuras

בְּחִינָה UVCHANUNI · MALACHI 3:10

Malachi traz uma frase rara nas escrituras: provai-me nisto, diz o texto, testai e vede se a promessa se cumpre. É um convite a verificar em vez de confiar cegamente, e é exatamente o que o teste automatizado faz pelo código. Sem teste, toda afirmação sobre o software é fé: acho que funciona, acho que a mudança não quebrou nada, acho que o caso raro está tratado. Com teste, a fé vira verificação: o código é provado, repetidamente, e a afirmação passa a ter respaldo. E o efeito mais valioso não é achar bug, é devolver a coragem de mudar, porque quem tem uma rede sob os pés se atreve a caminhar na corda, e quem não tem congela.

O teste é a rede que devolve a coragem de mudar

A pergunta que mais trava software não é como faço, é o que isto quebra se eu mexer. Sem teste, a resposta é desconhecida, e o desconhecido gera medo, e o medo gera código que ninguém toca, que envelhece e apodrece por falta de manutenção. O teste automatizado transforma esse desconhecido em resposta imediata: mexo, rodo os testes, e em segundos sei se quebrei algo que funcionava. Essa resposta rápida é o que devolve a coragem de refatorar, de melhorar, de evoluir, porque o custo de errar cai de um incidente em produção para uma luz vermelha na máquina.

É por isso que o valor do teste não se mede só em bugs encontrados, se mede em mudanças ousadas que ele viabiliza. Um sistema bem testado convida à melhoria contínua; um sistema sem teste pune qualquer mudança com o risco do desconhecido, e o time aprende a não mexer, acumulando dívida. O teste é a infraestrutura que sustenta tudo o mais deste eixo: não se refatora com segurança sem teste, não se aplica SOLID sem teste que prove que a extração não quebrou nada, não se entrega rápido sem teste que dê o sinal verde. Provai-me nisto é o convite que o código faz a cada mudança, e o teste é quem responde.

Figura 1O que o teste automatizado devolve ao time
  • REDECoragem de mudarrefatorar e melhorar sem apostar no escuro
  • FASTResposta rápidasegundos para saber se a mudança quebrou algo
  • DOCDocumentação vivao teste mostra como o código deve ser usado
  • DESIGNPressão de designcódigo difícil de testar é código mal desenhado
  • REGREGuarda contra regressãoo bug corrigido não volta sem avisar
  • GATESinal verde do deploya base para entregar rápido com confiança
O valor do teste não se mede só em bugs encontrados, se mede em mudanças ousadas que ele viabiliza. É a infraestrutura que sustenta refatoração, SOLID e entrega rápida: sem ela, o time aprende a não mexer.

A pirâmide: muitos rápidos na base, poucos lentos no topo

Nem todo teste é igual, e a pirâmide de testes, popularizada por Mike Cohn, diz onde investir. Na base, larga, ficam os testes de unidade: rápidos, isolados, testando uma peça pequena sem tocar em banco ou rede. São muitos, rodam em milissegundos, e apontam com precisão o que quebrou. No meio, os testes de integração, que verificam se as peças conversam, mais lentos e menos numerosos. No topo, estreito, os testes de ponta a ponta, que exercitam o sistema inteiro como o usuário: valiosos porque provam o fluxo real, mas lentos, frágeis e caros de manter, então poucos.

A forma da pirâmide não é estética, é economia. Testes de unidade dão o máximo de confiança pelo mínimo de custo e tempo; testes de ponta a ponta dão confiança de fluxo real, mas cobram caro em lentidão e instabilidade. O antipadrão mais comum é o cone de sorvete invertido: poucos testes de unidade e uma montanha de testes de ponta a ponta lentos e instáveis, que demoram para rodar, quebram por qualquer coisa, e o time acaba ignorando. Investir na base é o que dá uma suíte rápida o bastante para rodar a cada mudança, e é a velocidade da suíte que decide se ela é usada ou abandonada.

Figura 2Os níveis da pirâmide de testes
NívelO que testaQuantidadeCusto e velocidade
Unidadeuma peça pequena, isoladamuitos, a base largarápido, barato, aponta o que quebrou
Integraçãoas peças conversando entre sialguns, o meiomais lento, ainda gerenciável
Ponta a pontao sistema inteiro como o usuáriopoucos, o topo estreitolento, frágil, caro de manter
Cone invertidomuito e2e, pouca unidadeo antipadrãosuíte lenta e instável que o time ignora
A forma da pirâmide é economia, não estética. Unidade dá o máximo de confiança pelo mínimo de custo; e2e cobra caro. O cone de sorvete invertido produz uma suíte lenta que o time acaba abandonando.

TDD: o teste antes do código, como pressão de design

O desenvolvimento orientado a testes, o TDD de Kent Beck, inverte a ordem intuitiva: escreve-se o teste antes do código que ele testa. O ciclo é curto e disciplinado, red-green-refactor. Vermelho: escreve um teste que falha, porque o código ainda não existe. Verde: escreve o mínimo de código para o teste passar, sem elegância, só passar. Refatorar: agora, com o teste como rede, melhora o código sem medo de quebrar. E repete, um pequeno ciclo de cada vez, deixando a suíte crescer junto com o código.

O que torna o TDD poderoso não é a ordem em si, é a pressão de design que escrever o teste primeiro exerce. Ao escrever o teste antes, você é obrigado a pensar como o código será usado antes de pensar como ele funciona por dentro, e código difícil de testar denuncia, na hora, um design ruim: dependência escondida, responsabilidade demais, acoplamento forte. O teste é o primeiro cliente da sua API, e um cliente exigente melhora o produto. Nem todo mundo pratica TDD estrito, e há debate saudável sobre quando ele compensa, mas a ideia central, deixar a testabilidade guiar o design, vale mesmo para quem escreve o teste logo depois em vez de logo antes.

Figura 3O ciclo red-green-refactor do TDD
o teste guiao design 1234VermelhoVerdeRefatorarRepetir
  1. Vermelho escreve um teste que falha; o código ainda não existe
  2. Verde escreve o mínimo para o teste passar, sem se preocupar com beleza
  3. Refatorar melhora o código com o teste como rede, sem medo de quebrar
  4. Repetir um pequeno ciclo de cada vez, a suíte cresce com o código
O poder do TDD não é a ordem, é a pressão de design: escrever o teste antes obriga a pensar como o código será usado antes de como funciona. Código difícil de testar denuncia, na hora, design ruim.

Cobertura não é confiança

A métrica mais perseguida e mais mal entendida em testes é a cobertura: o percentual de linhas que os testes executam. Ela é útil como sinal negativo, código sem nenhuma cobertura certamente não está testado, mas é traiçoeira como meta. Cem por cento de cobertura não significa cem por cento de confiança, porque executar uma linha não é o mesmo que verificar seu comportamento. É trivial escrever um teste que roda todo o código e não afirma nada, ou que afirma o trivial e ignora o caso que de fato quebra. Cobertura mede o que foi tocado, não o que foi provado.

Perseguir cobertura como meta produz a pior espécie de teste: o teste que existe para subir o número, não para pegar o erro. Ele testa o getter, ignora a regra de negócio complexa, e dá ao time uma falsa sensação de segurança, pior que não ter teste, porque o alerta que deveria disparar foi desligado por um teste que não verifica nada de real. É a lei de Goodhart de novo: quando a cobertura vira meta, deixa de medir qualidade. A pergunta certa não é qual o percentual de cobertura, é os testes provam o comportamento que importa, e falham quando eu quebro algo real? Confiança se mede quebrando o código de propósito e vendo se o teste pega, não contando linhas executadas.

Figura 4Cobertura contra confiança: o que a suíte realmente prova
Confiança (o teste falha quando quebro algo real)
Suíte que protegecobertura alta e confiança alta: testa o que importa e pega o erro real.
Foco no que importacobertura média mas confiança alta: cobre a regra crítica, ignora o trivial.
Teatro de testecobertura alta mas confiança baixa: roda tudo, afirma nada, falsa segurança.
Sem redecobertura baixa e confiança baixa: código no escuro.
Cobertura (linhas que o teste executa)
Cobertura mede o que foi tocado, não o que foi provado. Perseguida como meta, produz teatro de teste: pior que não ter teste, porque desliga o alerta com um teste que não verifica nada real.

A maturidade de teste, e a cultura que a sustenta

A cultura de teste amadurece do medo à confiança. No começo é sem teste, mudança no escuro. Depois vêm testes escritos depois, para subir cobertura, muitos deles teatro. No meio vem a pirâmide saudável, com base de unidade rápida. No topo é o teste como parte inseparável de escrever código, com testabilidade guiando o design, suíte rápida e confiável rodando a cada mudança, e testes de mutação garantindo que a rede de fato segura. Cada degrau troca a fé pela verificação, e o medo de mexer pela coragem de melhorar.

Teste não vive isolado: ele é a fundação da refatoração, que sem rede é temerária; do SSDLC, cujos testes de segurança são parentes; da entrega progressiva, cujo sinal verde ele fornece; e das métricas DORA, cuja taxa de falha ele derruba. Mas a lição mais profunda de Malachi é o convite à verificação em si: provai-me nisto é a recusa de aceitar promessa sem prova, seja no código, seja na afirmação de que o número do README está certo, seja no modelo de IA que diz funcionar. A cultura de provar antes de confiar, que o teste automatizado encarna, é o que separa a engenharia que sabe da engenharia que acha, e é a mesma disciplina que atravessa todo o resto do que eu escrevo e opero.

Figura 5Maturidade da cultura de testes
  1. 0Sem testetoda mudança é aposta no escuro
  2. 1Teste depoisescrito para subir cobertura, muito teatro
  3. 2Pirâmidebase de unidade rápida, e2e no lugar certo
  4. 3Suíte confiávelrápida, sem flaky, rodada a cada mudança
  5. 4Guia de designtestabilidade guia o desenho, teste antes ou junto
  6. 5Prova vivamutação garante a rede; provar antes de confiar é cultura
Cada degrau troca fé por verificação. A lição de Malachi, provai-me nisto, é a recusa de aceitar promessa sem prova, e atravessa código, README e modelo de IA por igual.

Para levar

Teste automatizado é o provai-me nisto de Malachi aplicado ao código: a recusa de confiar sem verificar, e a rede que devolve a coragem de mudar. A pirâmide diz onde investir, muitos testes de unidade rápidos na base; o TDD usa o teste como pressão de design, com o ciclo red-green-refactor; e a lição dura é que cobertura não é confiança, porque executar uma linha não é provar seu comportamento. A IA gera o caso de borda e caça o teatro por mutação. Mas garantir que o teste prova o que importa, e não só o que já existe, continua sendo julgamento de quem conhece a intenção do código.

Tags

  • #julianovincedecampos
  • #Testes
  • #TDD
  • #Engenharia
  • #Qualidade
  • #PirâmideDeTestes
  • #Automação

Onde eu estudei, me certifiquei e trabalhei

  • University of Cambridge
  • PUC Minas
  • PUC-RS
  • PUC Goiás
  • Pontificia Universidad Católica del Perú
  • Amazon Web Services
  • Google
  • IBM
  • Oracle
  • COBIT 5 Foundation
  • ITIL v3 Foundation
  • Exemplar Global
  • Red Team Leaders
  • Infosec
  • Salesforce
  • Flowgrammers
  • ISO/IEC 27001
  • NIST Cybersecurity Framework
  • Compass UOL
  • Luby
  • Creditas
  • PicPay
  • PagoNxt, Santander
  • Mercado Pago
  • Itaú Unibanco
  • Foursys
  • Soluti Certificação Digital