Testes que realmente detectam erros: além da cobertura e do quality gate em verde
Por Dorian Chávez · fundador da Hábil e arquiteto de integração ·
Cobertura alta e quality gate em verde não bastam: tipos de teste, dublês que escondem falhas, mutação, IA e documentação para testes que detectam erros.
Cenário ilustrativo. Uma equipe de pagamentos de uma fintech abre o painel em uma sexta-feira: a cobertura de testes está em 91 %, a análise de qualidade de código marca verde e o pipeline —a linha automática que constrói, testa e entrega o software— terminou sem erros. Na segunda-feira, um grupo de clientes reporta cobranças duplicadas. Ninguém mentiu e nenhuma ferramenta falhou: cada uma mediu o que sabe medir. O que ninguém havia medido é se os testes, que eram muitos, teriam alertado para esse defeito em particular.
Este artigo é para quem responde por essa diferença: o CTO ou o diretor de tecnologia de um banco, uma fintech, uma seguradora, uma rede de varejo ou uma empresa regulada. Explica o que a cobertura e o quality gate (o «portão de qualidade»: um conjunto de condições que o código deve cumprir para avançar) realmente medem, que tipos de teste existem e que falha cada um detecta, como se verifica que um teste serve, que papel desempenham a inteligência artificial e a documentação do código, e por onde começar. Inclui o que medimos na nossa própria plataforma, porque alguns desses achados foram incômodos.
O que um painel em verde realmente mede
Convém começar pelo que dizem as próprias ferramentas.
A cobertura responde a uma única pergunta: esta linha de código foi executada enquanto os testes rodavam? O SonarQube, uma ferramenta de análise de qualidade de código, define a cobertura de linhas como linhas cobertas divididas por linhas executáveis, e a de condições como os ramos verdadeiros e falsos percorridos divididos pelo dobro de condições [11]. Executar uma linha não é comprovar que ela faz a coisa certa: um teste sem nenhuma verificação (uma «asserção», a comparação entre o que se esperava e o que ocorreu) pode aumentar a cobertura sem detectar nada.
O quality gate do SonarQube é um conjunto de condições configuráveis. O padrão, chamado «Sonar way», pede no código novo: sem problemas novos, cobertura de pelo menos 80 %, duplicação de 3 % ou menos e os pontos sensíveis de segurança revisados [10] [Dado do Sonar: valores padrão do fornecedor]; cada organização os ajusta. A cobertura de linhas só diz se uma linha foi executada; a métrica total do Sonar combina linhas e condições. Além disso, o Sonar não gera a cobertura: importa-a de outra ferramenta que roda os testes antes da análise [12]. Do que ele mede deduz-se o que não faz: não executa uma transferência, nem uma conciliação, nem uma emissão de apólice, nem um pagamento no comércio eletrônico. Essa leitura é nossa, não uma frase do Sonar, mas é coerente com o que a documentação dele descreve.
Também não há um número mágico de cobertura. Martin Fowler, referência em engenharia de software, a considera uma ferramenta para encontrar código sem teste, não uma meta; vê como razoável uma cobertura na faixa dos 80 % altos ou dos 90 %, trata os 100 % como sinal de alerta e adverte que impor um mínimo convida a escrever testes vazios para alcançá-lo [9]. Um estudo acadêmico clássico, de Inozemtseva e Holmes (2014), encontrou que a cobertura não tem uma correlação forte com a efetividade de um conjunto de testes uma vez descontado o tamanho dele [21].
E o «verde» significa coisas distintas conforme quem configura o portão. Em uma revisão interna da nossa plataforma comprovamos que a análise de um projeto recém-criado era aprovada com 3 condições ativas, enquanto a de um projeto maduro exigia 14. A mesma cor, dois níveis de exigência muito distintos.
As duas formas mais comuns de falso verde
1. Os dublês que respondem o que se espera
Para testar rápido, as equipes substituem as peças externas —o banco de dados, o provedor de pagamentos, outro serviço— por dublês de teste: imitações que respondem de forma predefinida. Fowler distingue vários tipos: os stubs (respostas enlatadas), os fakes (implementações simplificadas, mas funcionais), os spies (que registram como foram usados) e os mocks (que trazem expectativas pré-programadas) [8]. São úteis para manter os testes rápidos e isolados.
O risco é simples de enunciar: se o dublê responde o que o programador acredita que o sistema real responde, o teste passa mesmo que o sistema real responda outra coisa. Um dublê pode responder «200 OK» enquanto o provedor real rejeita o cabeçalho, a codificação, o certificado ou o formato da data. Fowler assinala ainda que os testes baseados em mocks ficam mais acoplados à implementação: se o código é reorganizado sem mudar o que faz, esses testes quebram; e se o sistema real muda, continuam passando [7].
Por isso os testes devem ser levados a conectividade real onde a decisão é tomada pela dependência e não pelo código: o banco de dados com o motor real, o barramento de mensagens com o dele, o contrato com o provedor verificado contra o provedor. Para as dependências que podem ser conteinerizadas, ferramentas como o Testcontainers sobem um banco de dados ou uma fila reais e descartáveis enquanto o teste roda e os destroem ao terminar; o próprio guia delas propõe substituir os bancos em memória pelo banco real [13]. Para provedores externos, continua-se a usar sandbox, contrato ou um dublê observável: um contêiner não substitui as credenciais, a homologação nem a autorização de um terceiro real.
2. Os testes que abençoam o erro
Um teste escrito a partir do que o código faz, e não do que deve fazer, certifica o defeito. Um exemplo simples: a regra de negócio diz que se bloqueiam os valores de 10.000 pesos ou mais, mas o código bloqueia somente os maiores que 10.000, e o teste, escrito olhando o código, verifica o comportamento atual. Há cobertura completa, tudo está em verde e a regra é descumprida. É um risco conhecido dos testes escritos por pessoas e, como veremos, um risco maior nos que uma IA escreve.
Nenhuma das duas formas aparece no painel. Aparecem ao fazer perguntas distintas à suíte de testes, e disso trata o resto do artigo.
Os tipos de teste e a falha que cada um pode detectar
Nenhum tipo de teste cobre sozinho todos os riscos relevantes. Cada tipo pode trazer evidência que os demais não trazem para aquele fluxo. Esta é a lista que usamos para explicar a um comitê:
| Tipo | O que executa | O que pode detectar | O que não vê | Ferramentas de exemplo |
|---|---|---|---|---|
| Unitário | Uma função ou classe isolada | Cálculos, limites, validações, regras locais | Que as peças se encaixem entre si | JUnit, pytest, Go testing, Jest, Vitest |
| Integração com dependências reais | O código mais um banco de dados, um barramento ou um serviço reais e descartáveis | Migrações quebradas, consultas que falham contra o esquema real, serialização, configuração, transações | Fluxos completos de usuário | Testcontainers |
| Contrato | O consumidor e o provedor de uma API, cada um contra o que foi pactuado | Um campo renomeado, um tipo alterado, um cabeçalho diferente que quebraria o consumidor | A lógica interna do provedor | Pact |
| Coleção de API | Requisições HTTP contra um ambiente, com verificações | Códigos de resposta, formatos, autenticação, autorização, regressões de um serviço | O comportamento interno | Postman, Postman CLI, Newman |
| De navegador (ponta a ponta) | Uma pessoa simulada, o navegador, o frontend e o backend integrados | Rotas, cookies, login, renderização, fluxos críticos | Detalhes finos; são lentos e frágeis se usados em excesso | Playwright |
| De mutação | A suíte contra versões deliberadamente danificadas do código | Testes que executam código sem detectar mudanças | Se a regra de negócio em si está correta | PIT (Java), Stryker (JavaScript/TypeScript, C#, Scala) |
Alguns esclarecimentos que importam para decidir:
- Contrato. O Pact verifica o provedor que a equipe controla; não valida necessariamente o terceiro real. Ele trabalha «dirigido pelo consumidor»: testa-se somente o que o consumidor realmente usa; o consumidor gera um arquivo com as expectativas dele e o provedor o verifica contra o serviço real [14]. Evita montar testes integrados custosos entre duas equipes. Os próprios documentos dele declaram os limites da ferramenta: não serve para testes funcionais, de carga, para APIs públicas nem quando não se controlam os dois lados [14].
- Coleções de API. O Postman permite escrever verificações em JavaScript por requisição, pasta ou coleção [15]. Um dado prático que poucos mencionam: o Newman, o executor de coleções por linha de comando, segue disponível para os fluxos existentes, mas o repositório oficial indica que o desenvolvimento ativo se limita à manutenção essencial e que, para fluxos novos, recomendam a Postman CLI [16]. Se a empresa já tem coleções rodando no Newman, não há urgência; se vai começar, convém começar pela ferramenta vigente.
- Navegador. Um teste de navegador nem sempre é de ponta a ponta: pode simular terceiros. O Playwright cobre Chromium, WebKit e Firefox, e as boas práticas dela pedem testar o que o usuário vê, isolar cada teste e simular os sites de terceiros em vez de testá-los [17]. É o tipo mais parecido com o uso real, e por isso é reservado para poucos percursos de alto valor.
- Mutação. Explica-se em uma frase: é sabotar o sistema de propósito para ver se o alarme toca. Desenvolve-se mais adiante.
Ferramentas por camada
| Camada | Ferramentas de exemplo | Para quê |
|---|---|---|
| Backend Java | JUnit, Testcontainers, PIT | Regras de negócio, integração com infraestrutura, mutação do código crítico |
| Backend Python | pytest (com as fixtures, dados e recursos de apoio reutilizáveis) | Regras, parametrização, integração |
| Backend Go | testing e go test, parte da biblioteca padrão; admite testes de fuzzing (entradas aleatórias) | Unidades, integração, entradas inesperadas |
| Frontend (JavaScript/TypeScript) | Jest ou Vitest, com Testing Library | Lógica de interface e componentes, testados como uma pessoa os usa |
| Frontend, percursos completos | Playwright | Fluxos críticos e compatibilidade entre navegadores |
| JavaScript/TypeScript, mutação | StrykerJS sobre Jest ou Vitest | Detectar testes fracos |
A Testing Library formula o princípio com clareza: quanto mais um teste se parece com a forma como o software é usado, mais confiança dá [20]. O Jest declara que o Vite não é oficialmente suportado e sugere o Vitest nesse caso [20]; é um exemplo de por que a ferramenta é escolhida conforme o resto do stack, não por moda.
Por que mais tipos de teste rendem mais do que mais testes do mesmo tipo
A afirmação correta não é «quanto mais tipos, melhor» sem limite. É esta: para um dado risco, convém investir no tipo de teste que cobre uma classe de falha que ainda ninguém cobriu.
Dez testes unitários a mais sobre um arredondamento não vão descobrir uma migração de banco de dados que falha, um contrato HTTP incompatível, uma sessão que se perde entre telas ou uma dependência que demora demais. Isso é detectado por outros tipos. A evidência de pesquisa sobre diversidade de testes vai nessa linha: critérios que distinguem comportamentos distintos podem encontrar falhas que os critérios tradicionais não veem, com um custo adicional [23].
A outra metade do equilíbrio é não ir ao extremo oposto. Os testes de navegador são os mais parecidos com o uso real, mas também os mais lentos e frágeis. Fowler os descreve como frágeis, caros de escrever e lentos de rodar [1]. No estudo do Google sobre cerca de 4,2 milhões de testes próprios, os testes maiores foram mais instáveis, isto é, passam e falham sem que o código mude; o WebDriver e o emulador Android mostraram taxas acima da média entre as ferramentas analisadas, e o próprio autor ressalva que correlação não é causalidade [5] [Dado do Google, 2017; não universal]. O guia dele recomenda, aproximadamente, 70 % de testes pequenos, 20 % de integração e 10 % de ponta a ponta [4] [Dado do Google, 2015; não universal]. É uma orientação de uma empresa, não uma norma; há quem sustente que discutir porcentagens distrai [3]. Fowler e o Google recomendam reservar os testes amplos para os riscos que os justificam; a proporção depende do sistema, e Fowler adverte que a pirâmide tem exceções [1][4].
Um exemplo para um comitê: três mil testes unitários com dublês, sem testes de contrato, significam que um campo renomeado em uma API quebra todos os consumidores dela em produção sem que nenhum painel avise. Esses mesmos três mil, sem integração real, significam que ninguém testou a consulta contra o esquema de verdade. E se tudo isso existe mas nenhum teste percorre o fluxo completo, ninguém sabe se o cliente consegue concluir a compra. Cada tipo de teste pode cobrir uma classe de falha que os demais não veem; concentrar tudo em um tipo é concentrar o risco.
O que medimos na nossa própria plataforma
A Hábil constrói uma plataforma modular de integração. Em uma medição recente, sobre os 34 serviços dela, contamos 1.407 classes de teste e cerca de 9.800 métodos de teste automatizados (duas formas distintas de contá-los deram 9.771 e 9.839) [37]. Com essa quantidade, seria de esperar tranquilidade. Estes são aprendizados, já corrigidos, de casos em que a tranquilidade era injustificada. Os números são nossos e não foram auditados externamente.
O pagamento que era feito 12 vezes. Um teste de um fluxo de pagamentos se chamava «não duplica» e estava em verde. Verificava um contador interno do próprio serviço, não a chamada ao provedor de pagamentos. Ao ser reescrito para verificar a chamada real, falhou: esperava-se 1 e houve 2. Com um servidor falso que conta quantas vezes é chamado, 12 tentativas simultâneas produziram 12 pagamentos. Após a correção, produziram 1. Note-se a diferença entre duas classes de dublê: um que responde o que se espera, que esconde o defeito, e um que registra o que de fato lhe chega, que o expõe.
Os 17 de 19 campos perdidos. Uma mudança em uma função de extração de dados passou por toda a suíte, que usava documentos de amostra sintéticos. Com documentos reais, a mudança perdia 3 de 4 campos em um tipo de documento e 17 de 19 em um documento estrangeiro. Os testes não estavam mal escritos: estavam alimentados com dados que não se pareciam com os reais.
A rejeição que cortava um canal. Uma rejeição legítima do provedor, repetida várias vezes, fazia disparar o circuit breaker (disjuntor), o mecanismo que corta as chamadas a um serviço que parece fora do ar. O efeito era cortar o canal inteiro. Estava presente em 7 serviços. Os dublês de teste não repetiam a rejeição, então o defeito não tinha por onde aparecer.
Cinco testes verdes que sustentavam defeitos. Encontramos cinco testes em verde que sustentavam defeitos, de três tipos: o que abençoa o erro com nome explícito, o que simula um desfecho impossível e o permissivo demais. Exercitar o sistema real descartou 9 achados nossos e confirmou outros: verificar ao vivo corrige nas duas direções.
O sucesso sem trabalho. Dois falsos verdes de medição, dos mais traiçoeiros: uma construção que terminou com a mensagem de sucesso sem ter executado nenhum teste, e uma execução de testes passada por um filtro de texto que interrompeu o processo pela metade e reportou 113 e 401 testes onde na realidade rodavam 518. A saída parecia uma contagem válida. Lição: o número de testes é lido do relatório, não do código de saída de um comando.
Os cinco casos têm uma raiz comum: em cada um, o sinal verde estava bem construído e respondia honestamente à pergunta que lhe era feita. Mas a pergunta estava errada.
Como saber se um teste serve?
Há duas respostas, uma artesanal e uma automatizada.
A artesanal: reverter a correção e ver o teste ficar vermelho. Se um teste foi escrito para proteger uma correção, desfaz-se a correção e roda-se o teste: ele tem de falhar. Se continua em verde, não estava protegendo nada. Para um defeito novo, a regra equivalente é escrever primeiro o teste que falha e depois corrigir; o guia oficial do Claude Code, por exemplo, pede assim para os erros [28]. É barata e exige disciplina. Na nossa plataforma a usamos como régua: as 6 mutações manuais que fizemos foram detectadas.
Há uma armadilha mais sutil que convém conhecer, porque não aparece na literatura que revisamos: um teste pode passar também com o defeito. Em uma de nossas correções, o critério dizia «após a rejeição, o saldo volta ao valor anterior». Ao revisar, notamos que essa verificação passava igual com o erro, porque separar um valor e devolvê-lo deixam o mesmo número. O que de fato distinguia era o registro de operações: com o defeito apareciam duas gravações; com a correção, nenhuma. A pergunta que vale a pena fazer a cada teste importante é simples: passaria também se o erro continuasse ali?
A automatizada: o teste de mutação. Ferramentas como o PIT (para Java) e o Stryker (para JavaScript, TypeScript, C# e Scala) modificam automaticamente o código —trocam um «maior que» por «maior ou igual», invertem uma condição, eliminam uma chamada— e rodam a suíte [18][19]. Se algum teste falha, a mudança «morre»; se todos passam, a mudança «sobrevive» e revela um teste que faltava. A porcentagem de mudanças detectadas se chama mutation score: se de 100 sabotagens a suíte pega 80, o score é 80 %. O PIT diz isso com clareza: a cobertura tradicional mede apenas o que é executado, não se os testes poderiam detectar uma falha [18]. Um estudo do FSE 2014 encontrou que os mutantes são um substituto válido das falhas reais para avaliar testes [22].
A mutação tem limites que um CTO deve conhecer:
- É lenta. Por isso convém aplicá-la ao código que mudou ou ao código crítico, não ao repositório inteiro; a própria documentação do PIT o recomenda [18].
- Tem ruído. Existem «mutantes equivalentes»: mudanças que não alteram o comportamento e que nenhum teste poderia detectar [18]. Um estudo industrial reportou que a detecção automática desses mutantes melhora muito com um pré-processamento prévio, o que indica que o próprio controle tem margem de erro [27].
- Não certifica o negócio. Se o teste abençoa uma regra errada, pode até «matar» a mudança que corrige o código. A pesquisa respalda usar a mutação como guia, não como indicador único: a relação dela com os defeitos reais depende do tamanho e do contexto da suíte [23].
Por isso a qualidade é medida como um conjunto de sinais, cada um com a pergunta que responde:
| Sinal | Pergunta que responde |
|---|---|
| Cobertura | Que código foi executado? |
| Mutação | As verificações detectam mudanças plausíveis? |
| Contratos verificados | Consumidor e provedor continuam compatíveis? |
| API e navegador em percursos críticos | O fluxo real funciona no ambiente-alvo? |
| Rastreabilidade entre requisito e teste | A expectativa vem de uma regra aprovada, ou do que o código já fazia? |
| Defeitos que chegaram à produção | A evidência continua prevendo o que acontece em produção? |
Mesmo com conectividade real, coisas podem acontecer
Levar os testes a dependências reais reduz uma classe de risco; não a elimina. Um ambiente de testes não é produção: tem menos dados, outra latência, outras credenciais e, com frequência, outra versão do provedor. Um terceiro pode mudar o comportamento dele sem avisar. Uma carga que não foi simulada pode mostrar um defeito de concorrência. E os fluxos que só ocorrem uma vez por mês, como o fechamento contábil ou a renovação anual de uma apólice, raramente estão na suíte. Este mapa cobre principalmente comportamento funcional e compatibilidade; desempenho, segurança e continuidade exigem controles específicos conforme o risco.
Por isso a estratégia sensata tem duas metades. A primeira, mais tipos de teste automatizado, cada um apontado para uma classe de falha. A segunda, o que ocorre depois de liberar: observar o que o sistema faz, poder dar marcha à ré e revisar com calma o que escapou. Cada defeito que chega à produção é informação: indica que tipo de teste faltava, e a resposta correta costuma ser acrescentar esse teste, não só corrigir o código. Essa conversa, a de liberar com controle, desenvolvemos em «Liberar sem medo na infraestrutura própria».
A inteligência artificial: acelera, mas precisa de um filtro
A IA ajuda a construir testes: propõe casos-limite, gera esqueletos, monta coleções de API, explica uma falha. A produção dela tem um perfil conhecido.
O que a evidência mostra. Um estudo industrial da Meta sobre geração de testes com modelos de linguagem mediu que 75 % dos casos compilava, 57 % passava de forma confiável e 73 % das recomendações foi aceito pelos engenheiros [Estudo da Meta, amostra específica]; tudo isso depois de filtros automáticos que descartam o que não compila, não passa ou não acrescenta cobertura [24]. Um estudo sobre 25 pacotes de JavaScript encontrou uma mediana de 70,2 % de cobertura de sentenças e 52,8 % de ramos com um modelo de uso geral [25]. São cifras de modelos de 2023 e 2024; as de hoje serão distintas, mas a direção é instrutiva: sem filtros, uma parte importante do que é gerado não serve.
O risco central. A IA tende a copiar o que o código faz, não o que deve fazer. Um estudo sobre 24 repositórios de Java concluiu que os testes gerados com modelos de linguagem capturam sobretudo o comportamento atual, o que dificulta detectar erros [26]. É o teste que abençoa o erro, produzido à velocidade de máquina. Outros riscos documentados: verificações superficiais que inflam a cobertura, métodos ou regras inventados, e dados sensíveis que saem para um terceiro. Um estudo histórico sobre um assistente de código encontrou vulnerabilidades em cerca de 40 % de 1.689 programas gerados para cenários específicos; é um resultado da época, não uma taxa aplicável aos modelos atuais [36].
O que fazer com isso. Os guias dos fornecedores coincidem no essencial, embora nenhum traga cifras próprias:
- Dar à IA uma verificação que ela mesma possa executar; o guia do Claude Code a chama de diferença entre uma sessão que se vigia e uma que se deixa sozinha, e pede que mostre a saída dos testes em vez de afirmar que passaram [28].
- Ser específico ao pedir testes: «acrescente testes a este arquivo» é o exemplo ruim; o bom nomeia o caso de borda e o que deve ser evitado [28].
- Revisar o que foi gerado e acrescentar os testes que faltarem, como indica o guia do GitHub Copilot [30].
- Vigiar o «verde a qualquer custo»: o guia da Anthropic adverte que o modelo pode se concentrar em fazer os testes passarem, até com valores fixos, e lembra que os testes existem para verificar a correção, não para definir a solução [29].
- Separar quem escreve de quem revisa. O guia do Claude Code sugere sessões distintas para escrever os testes e para escrever o código que os satisfaz [28].
- Não carregar dados de produção em ferramentas de IA nem em ambientes de teste sem classificação, mascaramento (ou dados sintéticos) e validação de privacidade, e revisar com o provedor a retenção e as condições contratuais.
- Passar o que foi gerado pela mutação: dar à IA os mutantes que sobreviveram permitiu detectar até 28 % mais trechos defeituosos de código escrito por pessoas do que a linha de base, em um estudo [27].
A política que resume tudo é curta: a IA propõe; a execução, a mutação e a revisão do domínio validam.
Por que documentar o código melhora os testes
O código só diz o que faz. O que deve fazer vive em outro lugar, e se não está escrito, a IA —e a pessoa nova na equipe— o deduz da implementação e copia os erros dela. É aí que entra a documentação.
Os comentários de documentação —Javadoc em Java, JSDoc e TSDoc em JavaScript e TypeScript, docstrings em Python— são, na prática, um contrato: o que uma função recebe, o que devolve, que exceções pode lançar, que efeitos colaterais tem [34]. A convenção do Python (PEP 257) pede documentar comportamento, argumentos, retorno, efeitos colaterais, exceções e restrições de uso [34]. Além disso, o doctest converte os exemplos escritos no docstring em testes executáveis: se um exemplo deixa de ser verdadeiro, a suíte avisa [34]; o que o docstring explica fora desses exemplos pode, sim, ficar desatualizado em silêncio.
Quanta evidência há de que isso melhora os testes? A resposta honesta é: aponta nessa direção, embora não tenhamos encontrado um experimento limpo de «mesmo código com e sem documentação». O que há são estudos próximos: converter documentação em linguagem natural em condições verificáveis com um modelo de linguagem permitiu detectar 64 erros históricos reais [33]; extrair regras da documentação de APIs de aprendizado profundo encontrou 94 erros contra 59 da linha de base sem essas restrições [33]; e um estudo de geração de verificações encontrou melhorias de 10 a 20 % ao incorporar o Javadoc [31]. A advertência vai no outro sentido: documentação falsa ou desatualizada pode prejudicar seriamente a compreensão do código por parte de um modelo [32]. Não basta documentar; é preciso manter correto o que foi documentado.
O terceiro elemento são os arquivos de contexto do repositório, como o AGENTS.md (formato aberto que vários assistentes de código leem, entre eles o Codex e o Copilot) ou o CLAUDE.md no caso do Claude Code [35]. Ali se escrevem os comandos para rodar os testes, as convenções e as armadilhas que não se deduzem lendo o código. Duas recomendações oficiais: que sejam curtos, porque se são longos o assistente ignora regras, e que não substituam os requisitos aprovados nem contenham segredos [28][35].
Na nossa plataforma documentamos o código para que uma pessoa nova possa se orientar sem ajuda. Não temos medido que isso tenha melhorado os testes que os assistentes escrevem, e não o afirmamos. O que medimos é o custo de não escrevê-lo: a documentação já dizia que certa opção de configuração não era exercitada fora do valor padrão, e a lacuna apareceu de qualquer maneira. Daí saiu uma regra prática: um teste de configuração deve demonstrar as duas direções, não só a usual.
Exemplos simples por setor
Todos são cenários ilustrativos, sem clientes nem cifras.
| Setor | Cenário | Que combinação de testes o detecta |
|---|---|---|
| Bancos | Uma transferência se duplica quando o app tenta de novo após uma conexão cortada | Unitário da idempotência (que repetir a mesma operação não a aplique duas vezes: tentar de novo não repete); integração com o banco real para comprovar que a restrição de unicidade funciona; contrato com o serviço de pagamentos; percurso de navegador da transferência ao comprovante |
| Fintech | Um depósito é creditado duas vezes quando o provedor repete o aviso | Unitário da chave de idempotência e dos valores; integração com o livro de saldos real; contrato do aviso; coleção de API para a assinatura inválida |
| Seguros | A cotação aplica uma franquia errada justamente na idade-limite | Unitário com as idades de fronteira (70 e 71, com e sem exame médico); mutação do motor de tarifas, porque ali um «maior que» por «maior ou igual» altera prêmios; percurso da cotação à emissão |
| Varejo | O checkout vende a última peça a dois clientes ao mesmo tempo | Integração com o estoque real e concorrência; contrato com pagamentos; alguns poucos testes de navegador do percurso de compra, com o gateway externo simulado |
| Empresa regulada | Um relatório regulatório mostra um total mal agregado | Unitários das regras de cálculo; integração contra o esquema real; mutação sobre a lógica de agregação; um requisito escrito no contexto do repositório que exija um teste de mascaramento de dados pessoais em logs |
Veja-se o caso de bancos. O unitário diz que a lógica está correta; o de integração demonstra que o banco rejeita o duplicado de verdade; o de contrato diz que o serviço de pagamentos entende a mesma identificação; o de navegador, que a pessoa vê um comprovante. Nenhum dos quatro, sozinho, traz a evidência dos outros três.
Por onde começar
- Meça o que a empresa já tem, de duas formas. Conte os testes pelo relatório da execução, não pelo código de saída, e compare com outro método. Verifique que condições ativas tem o quality gate de cada projeto e se são as mesmas.
- Escolha os cinco fluxos com mais dinheiro ou mais regulação em jogo —um pagamento, uma emissão, uma conciliação, um relatório— e pergunte de cada um: que tipo de teste o detectaria se quebrar, e existe hoje?
- Revise os dublês. Onde decide a dependência (banco, barramento, provedor), passe de um dublê que responde o esperado para uma dependência real ou para um dublê que registra o que de fato chega.
- Teste os testes. Escolha os dez mais importantes: reverta a correção e comprove que ficam vermelhos. No código crítico, avalie uma ferramenta de mutação restrita ao que muda.
- Ponha a IA dentro do mesmo controle. Que mostre a saída dos testes, que não encerre uma tarefa com verificações vazias e que cada teste gerado tenha um requisito escrito por trás.
- Escreva o que o sistema deve fazer onde os assistentes o leiam: documentação das regras críticas e um arquivo de contexto curto com os comandos e as armadilhas.
Em um diagnóstico, com escopo acordado, podemos construir um mapa dos fluxos críticos, da evidência existente e das lacunas priorizadas. Ele não substitui uma certificação de ausência de defeitos nem de conformidade. Quantos dos testes que hoje sustentam o verde da empresa ficam vermelhos se a correção é revertida? Esse é o próximo passo natural: o diagnóstico pode começar por respondê-lo com os fluxos da própria empresa.
Referências
- M. Fowler, Test Pyramid (2012). https://martinfowler.com/bliki/TestPyramid.html
- H. Vocke, The Practical Test Pyramid (2018). https://martinfowler.com/articles/practical-test-pyramid.html
- K. C. Dodds, The Testing Trophy and Testing Classifications (2018). https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications
- Google Testing Blog, Just Say No to More End-to-End Tests (2015). Guia de uma empresa, cifras aproximadas. https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html
- Google Testing Blog, Where do our flaky tests come from? (2017). Dado do Google, não universal. https://testing.googleblog.com/2017/04/where-do-our-flaky-tests-come-from.html
- Google Testing Blog, Test Sizes (2010). https://testing.googleblog.com/2010/12/test-sizes.html
- M. Fowler, Mocks Aren't Stubs. https://martinfowler.com/articles/mocksArentStubs.html
- M. Fowler, Test Double. https://martinfowler.com/bliki/TestDouble.html
- M. Fowler, Test Coverage. https://martinfowler.com/bliki/TestCoverage.html
- SonarQube, Introduction to quality gates (valores padrão do fornecedor, configuráveis), consultado em 6 de outubro de 2026. https://docs.sonarsource.com/sonarqube-server/quality-standards-administration/managing-quality-gates/introduction-to-quality-gates
- SonarQube, Metrics definition (cobertura de linhas e de condições), consultado em 6 de outubro de 2026. https://docs.sonarsource.com/sonarqube-server/user-guide/code-metrics/metrics-definition
- SonarQube, Test coverage overview, consultado em 6 de outubro de 2026. https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/test-coverage/overview
- Testcontainers, documentação e guias, consultado em 6 de outubro de 2026. https://java.testcontainers.org/ · https://testcontainers.com/guides/
- Pact, documentação (How Pact works, What is Pact good for), consultado em 6 de outubro de 2026. https://docs.pact.io/ · https://docs.pact.io/getting_started/what_is_pact_good_for
- Postman, Test scripts e Postman CLI overview, consultado em 6 de outubro de 2026. https://learning.postman.com/docs/tests-and-scripts/write-scripts/test-scripts/ · https://learning.postman.com/docs/postman-cli/postman-cli-overview/
- Newman, repositório oficial (README: manutenção limitada; Postman CLI para fluxos novos), consultado em 6 de outubro de 2026. https://github.com/postmanlabs/newman
- Playwright, Introduction, Best practices e Mock APIs, consultado em 6 de outubro de 2026. https://playwright.dev/docs/intro · https://playwright.dev/docs/best-practices · https://playwright.dev/docs/mock
- PIT Mutation Testing, site, mutadores e FAQ, consultado em 6 de outubro de 2026. https://pitest.org/ · https://pitest.org/faq/
- Stryker Mutator, documentação, consultado em 6 de outubro de 2026. https://stryker-mutator.io/docs/
- Documentação oficial de JUnit, pytest, Go
testing, Jest, Vitest e Testing Library, consultado em 6 de outubro de 2026. https://docs.junit.org/current/user-guide/ · https://docs.pytest.org/en/stable/ · https://pkg.go.dev/testing · https://jestjs.io/docs/getting-started · https://vitest.dev/guide/ · https://testing-library.com/docs/ - L. Inozemtseva e R. Holmes, Coverage Is Not Strongly Correlated with Test Suite Effectiveness, ICSE 2014. https://dl.acm.org/doi/10.1145/2568225.2568271
- R. Just et al., Are Mutants a Valid Substitute for Real Faults in Software Testing?, FSE 2014. https://dl.acm.org/doi/10.1145/2635868.2635929
- M. Papadakis et al., mutação e defeitos reais, ICSE 2018 (https://doi.org/10.1145/3180155.3180183); Shin, Papadakis e Kintis, diversidade de testes e mutação, IEEE TSE (https://doi.org/10.1109/TSE.2017.2732347).
- N. Alshahwan et al., Automated Unit Test Improvement using Large Language Models at Meta, FSE 2024, arXiv 2402.09171. https://arxiv.org/abs/2402.09171
- Schäfer et al., An Empirical Evaluation of Using Large Language Models for Automated Unit Test Generation, arXiv 2302.06527. https://arxiv.org/abs/2302.06527
- Estudo de oráculos de teste gerados com modelos de linguagem (24 repositórios Java), arXiv 2410.21136. https://arxiv.org/abs/2410.21136
- Testes com modelos de linguagem e mutação: arXiv 2308.16557 (mutantes sobreviventes no prompt, até 28 % mais trechos defeituosos detectados) e arXiv 2501.12862 (mutação dirigida na indústria). https://arxiv.org/abs/2308.16557 · https://arxiv.org/abs/2501.12862
- Anthropic, Claude Code, Best practices e Memory, consultado em 6 de outubro de 2026. https://code.claude.com/docs/en/best-practices · https://code.claude.com/docs/en/memory
- Anthropic, Claude prompting best practices, consultado em 6 de outubro de 2026. https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices
- GitHub, Copilot: write tests e Best practices, consultado em 6 de outubro de 2026. https://docs.github.com/en/copilot/tutorials/write-tests · https://docs.github.com/en/copilot/get-started/best-practices
- Liu et al., Doc2OracLL, 2025. https://doi.org/10.1145/3729354
- Macke e Doyle, documentação e compreensão de código por modelos de linguagem, NAACL Findings 2024. https://aclanthology.org/2024.findings-naacl.66/
- Documentação como insumo de testes: arXiv 2310.01831 (nl2postcond: linguagem natural para condições verificáveis, 64 erros históricos reais do Defects4J) e arXiv 2109.01002 (DocTer: regras extraídas da documentação de APIs de aprendizado profundo, 94 erros contra 59 da linha de base). https://arxiv.org/abs/2310.01831 · https://arxiv.org/abs/2109.01002
- Oracle, especificação de comentários Javadoc; JSDoc; TSDoc; PEP 257; documentação do
doctest, consultado em 6 de outubro de 2026. https://docs.oracle.com/en/java/javase/21/docs/specs/javadoc/doc-comment-spec.html · https://jsdoc.app/about-getting-started · https://tsdoc.org/ · https://peps.python.org/pep-0257/ · https://docs.python.org/3/library/doctest.html - AGENTS.md (formato aberto) e documentação do Codex e do GitHub Copilot sobre instruções do repositório, consultado em 6 de outubro de 2026. https://agents.md/ · https://learn.chatgpt.com/docs/agent-configuration/agents-md · https://docs.github.com/en/copilot/reference/custom-instructions-support
- Pearce et al., Asleep at the Keyboard? Assessing the Security of GitHub Copilot’s Code Contributions, IEEE Symposium on Security and Privacy, 2022 (https://doi.org/10.1109/SP46214.2022.9833571); versão em Communications of the ACM, 2025 (https://doi.org/10.1145/3610721).
- Hábil, medições próprias sobre a plataforma modular dela (34 serviços), 2026. Experiência da casa, sem auditoria externa.
- Nuvem e infraestrutura →
- Liberar sem medo na infraestrutura própria →
- APIs prontas para agentes de IA →
A operação da empresa enfrenta esses desafios?
Prefere e-mail? Escreva para hola@habil.mx