{"id":1053,"date":"2026-08-17T08:00:00","date_gmt":"2026-08-17T11:00:00","guid":{"rendered":"https:\/\/adrianosantostreina.com.br\/blog\/?p=1053"},"modified":"2026-08-13T14:26:50","modified_gmt":"2026-08-13T17:26:50","slug":"harness-de-testes-para-codigo-gerado-por-ia","status":"publish","type":"post","link":"https:\/\/adrianosantostreina.com.br\/blog\/harness-de-testes-para-codigo-gerado-por-ia\/","title":{"rendered":"Como Criar um Harness de Testes para C\u00f3digo Gerado por IA"},"content":{"rendered":"<p>Imagine a seguinte cena: voc\u00ea pede para um assistente de IA gerar uma fun\u00e7\u00e3o de valida\u00e7\u00e3o de CPF, ou um endpoint de API, ou uma rotina de c\u00e1lculo financeiro. O c\u00f3digo chega r\u00e1pido, bem formatado, com nomes de vari\u00e1veis sensatos e at\u00e9 coment\u00e1rios explicativos. Parece pronto. Voc\u00ea cola no projeto, executa manualmente uma ou duas vezes, v\u00ea que &#8220;funciona&#8221; e segue em frente. Semanas depois, um caso de borda que ningu\u00e9m testou explode em produ\u00e7\u00e3o \u2014 e a investiga\u00e7\u00e3o revela que aquele trecho gerado pela IA nunca foi validado de verdade, apenas validado visualmente.<\/p>\n<p>Esse cen\u00e1rio se repete com uma frequ\u00eancia preocupante nas equipes que adotaram ferramentas como Claude Code, Cursor, GitHub Copilot ou qualquer outro assistente de gera\u00e7\u00e3o de c\u00f3digo. O problema n\u00e3o \u00e9 a IA ser ruim \u2014 \u00e9 que c\u00f3digo gerado automaticamente precisa ser tratado com o mesmo rigor que c\u00f3digo de um desenvolvedor j\u00fanior no primeiro dia: promissor, mas n\u00e3o confi\u00e1vel at\u00e9 prova em contr\u00e1rio. E &#8220;prova em contr\u00e1rio&#8221;, em engenharia de software, tem nome: harness de testes.<\/p>\n<p>Neste artigo vamos construir, passo a passo, um harness de testes pensado especificamente para validar c\u00f3digo gerado por IA, com exemplos em m\u00faltiplas linguagens, estrat\u00e9gias de cobertura e uma estrutura que voc\u00ea pode adaptar ao seu stack \u2014 seja Python, TypeScript, Java, C# ou Delphi.<\/p>\n<h2>O que \u00e9 um Harness de Testes<\/h2>\n<p>Um harness de testes (do ingl\u00eas <em>test harness<\/em>) \u00e9 o conjunto de ferramentas, scripts, mocks, dados de entrada e infraestrutura que permite executar testes automatizados de forma consistente e repet\u00edvel, sem interven\u00e7\u00e3o manual. Pense nele como uma bancada de testes de laborat\u00f3rio: voc\u00ea n\u00e3o testa um componente eletr\u00f4nico apertando fios com a m\u00e3o a cada vez \u2014 voc\u00ea monta uma bancada com mult\u00edmetro, fonte de alimenta\u00e7\u00e3o e oscilosc\u00f3pio configurados uma vez, e depois s\u00f3 troca o componente sob teste.<\/p>\n<p>No contexto de c\u00f3digo gerado por IA, o harness cumpre um papel ainda mais cr\u00edtico do que em desenvolvimento tradicional, por tr\u00eas motivos:<\/p>\n<ul>\n<li><strong>Alucina\u00e7\u00e3o silenciosa:<\/strong> a IA pode gerar c\u00f3digo sintaticamente correto que resolve um problema ligeiramente diferente do que voc\u00ea pediu.<\/li>\n<li><strong>Falsa confian\u00e7a:<\/strong> c\u00f3digo bem formatado e com nomes descritivos passa uma sensa\u00e7\u00e3o de qualidade que nem sempre corresponde \u00e0 corre\u00e7\u00e3o l\u00f3gica.<\/li>\n<li><strong>Volume:<\/strong> quando voc\u00ea gera c\u00f3digo em maior velocidade, precisa validar em maior velocidade tamb\u00e9m \u2014 testes manuais n\u00e3o escalam.<\/li>\n<\/ul>\n<h3>Diferen\u00e7a entre Harness e Su\u00edte de Testes Comum<\/h3>\n<p>Uma su\u00edte de testes tradicional geralmente \u00e9 escrita pensando no comportamento esperado de c\u00f3digo que voc\u00ea mesmo projetou. Um harness para c\u00f3digo de IA precisa ser mais desconfiado por padr\u00e3o: ele assume que o c\u00f3digo pode estar sutilmente errado mesmo quando &#8220;parece&#8221; certo, e por isso incorpora camadas adicionais de verifica\u00e7\u00e3o, como testes de propriedades, testes de regress\u00e3o autom\u00e1tica e valida\u00e7\u00e3o de contratos de entrada e sa\u00edda.<\/p>\n<h2>Como Funciona: Anatomia de um Harness para C\u00f3digo de IA<\/h2>\n<p>Um harness robusto para esse cen\u00e1rio costuma ter quatro camadas:<\/p>\n<ul>\n<li><strong>Testes unit\u00e1rios determin\u00edsticos:<\/strong> casos conhecidos com entrada e sa\u00edda esperada, incluindo casos de borda.<\/li>\n<li><strong>Testes de propriedades (property-based testing):<\/strong> em vez de fixar exemplos, voc\u00ea define invariantes que devem ser verdadeiras para qualquer entrada v\u00e1lida.<\/li>\n<li><strong>Testes de contrato:<\/strong> validam tipos, formatos e limites de entrada\/sa\u00edda, especialmente \u00fateis quando a IA gera APIs ou integra\u00e7\u00f5es.<\/li>\n<li><strong>Sandbox de execu\u00e7\u00e3o isolada:<\/strong> ambiente controlado (container, processo isolado ou VM) onde o c\u00f3digo gerado roda sem acesso a recursos sens\u00edveis, evitando efeitos colaterais indesejados durante a valida\u00e7\u00e3o.<\/li>\n<\/ul>\n<h3>Passo 1: Isolar o C\u00f3digo Gerado em uma Interface Clara<\/h3>\n<p>O primeiro erro comum \u00e9 colar o c\u00f3digo da IA diretamente misturado com o restante da aplica\u00e7\u00e3o. Isso dificulta testar isoladamente. A pr\u00e1tica recomendada \u00e9 sempre gerar c\u00f3digo atr\u00e1s de uma interface ou contrato bem definido, mesmo que a implementa\u00e7\u00e3o venha de um prompt.<\/p>\n<pre><code class=\"language-typescript\">\/\/ contrato.ts\nexport interface ValidadorDocumento {\n  validar(documento: string): boolean;\n}\n\n\/\/ gerado-pela-ia.ts\nimport { ValidadorDocumento } from '.\/contrato';\n\nexport class ValidadorCPF implements ValidadorDocumento {\n  validar(cpf: string): boolean {\n    const numeros = cpf.replace(\/\\D\/g, '');\n    if (numeros.length !== 11 || \/^(\\d)\\1{10}$\/.test(numeros)) {\n      return false;\n    }\n    \/\/ l\u00f3gica de valida\u00e7\u00e3o dos d\u00edgitos verificadores...\n    return true;\n  }\n}\n<\/code><\/pre>\n<p>Com o contrato definido, o harness testa contra a interface, n\u00e3o contra a implementa\u00e7\u00e3o espec\u00edfica \u2014 o que permite trocar a implementa\u00e7\u00e3o gerada pela IA sem quebrar a su\u00edte de testes.<\/p>\n<h3>Passo 2: Testes Unit\u00e1rios com Casos de Borda Expl\u00edcitos<\/h3>\n<p>Pe\u00e7a sempre para a IA listar os casos de borda que ela considerou, e depois adicione os que ela n\u00e3o considerou. Usando <a href=\"https:\/\/jestjs.io\/pt-BR\/\" target=\"_blank\" rel=\"noopener\">Jest<\/a> como exemplo:<\/p>\n<pre><code class=\"language-typescript\">import { ValidadorCPF } from '..\/gerado-pela-ia';\n\ndescribe('ValidadorCPF gerado por IA', () =&gt; {\n  const validador = new ValidadorCPF();\n\n  test('rejeita CPF com todos os d\u00edgitos iguais', () =&gt; {\n    expect(validador.validar('111.111.111-11')).toBe(false);\n  });\n\n  test('rejeita CPF com menos de 11 d\u00edgitos', () =&gt; {\n    expect(validador.validar('123.456.789')).toBe(false);\n  });\n\n  test('aceita CPF v\u00e1lido conhecido', () =&gt; {\n    expect(validador.validar('529.982.247-25')).toBe(true);\n  });\n\n  test('rejeita string vazia', () =&gt; {\n    expect(validador.validar('')).toBe(false);\n  });\n\n  test('rejeita entrada com caracteres n\u00e3o num\u00e9ricos misturados incorretamente', () =&gt; {\n    expect(validador.validar('abc.def.ghi-jk')).toBe(false);\n  });\n});\n<\/code><\/pre>\n<p>Esses testes j\u00e1 pegariam boa parte dos erros t\u00edpicos de implementa\u00e7\u00f5es geradas \u00e0s pressas, como esquecer de tratar CPFs com d\u00edgitos repetidos (um erro cl\u00e1ssico que passa despercebido em revis\u00f5es visuais).<\/p>\n<h3>Passo 3: Testes de Propriedades para Cobrir o Que Voc\u00ea N\u00e3o Pensou<\/h3>\n<p>Testes de exemplo fixo cobrem apenas os casos que voc\u00ea imaginou. Testes de propriedades geram centenas de entradas aleat\u00f3rias e verificam invariantes. Em Python, a biblioteca <a href=\"https:\/\/hypothesis.readthedocs.io\/\" target=\"_blank\" rel=\"noopener\">Hypothesis<\/a> \u00e9 a refer\u00eancia:<\/p>\n<pre><code class=\"language-python\">from hypothesis import given, strategies as st\nfrom validador_gerado_pela_ia import calcular_desconto\n\n@given(preco=st.floats(min_value=0.01, max_value=1_000_000),\n       percentual=st.floats(min_value=0, max_value=100))\ndef test_desconto_nunca_e_negativo(preco, percentual):\n    resultado = calcular_desconto(preco, percentual)\n    assert resultado &gt;= 0\n\n@given(preco=st.floats(min_value=0.01, max_value=1_000_000),\n       percentual=st.floats(min_value=0, max_value=100))\ndef test_desconto_nunca_supera_o_preco_original(preco, percentual):\n    resultado = calcular_desconto(preco, percentual)\n    assert resultado &lt;= preco\n<\/code><\/pre>\n<p>Se a fun\u00e7\u00e3o gerada pela IA tiver um erro de sinal ou uma divis\u00e3o mal posicionada, o Hypothesis encontra o contraexemplo automaticamente e reporta a entrada exata que quebrou a invariante \u2014 algo praticamente imposs\u00edvel de descobrir s\u00f3 olhando o c\u00f3digo.<\/p>\n<h3>Passo 4: Sandbox de Execu\u00e7\u00e3o Isolada<\/h3>\n<p>Quando o c\u00f3digo gerado envolve acesso a arquivos, rede ou processos do sistema, \u00e9 fundamental execut\u00e1-lo em um ambiente isolado antes de confiar nele. Containers s\u00e3o a ferramenta natural para isso. Um exemplo simples com <a href=\"https:\/\/docs.docker.com\/\" target=\"_blank\" rel=\"noopener\">Docker<\/a>, rodando os testes em um container descart\u00e1vel:<\/p>\n<pre><code class=\"language-dockerfile\">FROM python:3.12-slim\n\nWORKDIR \/app\nCOPY . .\n\nRUN pip install --no-cache-dir -r requirements.txt\n\n# Sem acesso \u00e0 rede durante os testes, sem volumes persistentes montados\nCMD [\"pytest\", \"--maxfail=1\", \"--disable-warnings\", \"-q\"]\n<\/code><\/pre>\n<pre><code class=\"language-bash\">docker build -t harness-ia .\ndocker run --rm --network none harness-ia\n<\/code><\/pre>\n<p>A flag <code>--network none<\/code> garante que, se o c\u00f3digo gerado tentar fazer uma chamada externa inesperada (um comportamento que \u00e0s vezes aparece quando a IA &#8220;inventa&#8221; uma depend\u00eancia ou tenta buscar dados de uma API imagin\u00e1ria), o teste falhe de forma controlada em vez de causar efeitos colaterais reais.<\/p>\n<h3>Passo 5: Automatizando no Pipeline de CI<\/h3>\n<p>O harness s\u00f3 tem valor real se rodar automaticamente a cada gera\u00e7\u00e3o ou altera\u00e7\u00e3o de c\u00f3digo. Um exemplo de workflow com <a href=\"https:\/\/docs.github.com\/pt\/actions\" target=\"_blank\" rel=\"noopener\">GitHub Actions<\/a>:<\/p>\n<pre><code class=\"language-yaml\">name: harness-codigo-ia\n\non:\n  pull_request:\n    paths:\n      - 'src\/gerado-por-ia\/**'\n\njobs:\n  validar:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v4\n\n      - name: Configurar Node\n        uses: actions\/setup-node@v4\n        with:\n          node-version: '20'\n\n      - name: Instalar depend\u00eancias\n        run: npm ci\n\n      - name: Rodar testes unit\u00e1rios e de propriedades\n        run: npm test -- --coverage\n\n      - name: Verificar cobertura m\u00ednima\n        run: npx nyc check-coverage --lines 85 --functions 85 --branches 75\n<\/code><\/pre>\n<p>Note o gatilho baseado em <code>paths<\/code>: o pipeline dispara especificamente quando arquivos na pasta reservada para c\u00f3digo gerado por IA s\u00e3o alterados, tornando expl\u00edcito que esse c\u00f3digo passa por um crivo mais rigoroso.<\/p>\n<h3>Exemplo em Outro Ecossistema: Delphi<\/h3>\n<p>Para quem trabalha com Delphi, o mesmo princ\u00edpio se aplica usando <a href=\"https:\/\/github.com\/VSoftTechnologies\/DUnitX\" target=\"_blank\" rel=\"noopener\">DUnitX<\/a> como framework de testes:<\/p>\n<pre><code class=\"language-pascal\">unit TesteValidadorCPFGeradoPorIA;\n\ninterface\n\nuses\n  DUnitX.TestFramework, ValidadorCPFGeradoPorIA;\n\ntype\n  [TestFixture]\n  TTesteValidadorCPF = class\n  public\n    [Test]\n    procedure RejeitaCPFComDigitosRepetidos;\n\n    [Test]\n    procedure AceitaCPFValidoConhecido;\n  end;\n\nimplementation\n\nprocedure TTesteValidadorCPF.RejeitaCPFComDigitosRepetidos;\nbegin\n  Assert.IsFalse(TValidadorCPF.Validar('111.111.111-11'));\nend;\n\nprocedure TTesteValidadorCPF.AceitaCPFValidoConhecido;\nbegin\n  Assert.IsTrue(TValidadorCPF.Validar('529.982.247-25'));\nend;\n\ninitialization\n  TDUnitX.RegisterTestFixture(TTesteValidadorCPF);\n\nend.\n<\/code><\/pre>\n<p>A estrutura conceitual \u00e9 id\u00eantica \u00e0 do TypeScript: isolar em interface, cobrir casos de borda, automatizar a execu\u00e7\u00e3o. A linguagem muda, o rigor n\u00e3o.<\/p>\n<h2>Checklist Pr\u00e1tico para seu Harness<\/h2>\n<ul>\n<li>Todo c\u00f3digo gerado por IA entra atr\u00e1s de uma interface test\u00e1vel.<\/li>\n<li>Existem testes unit\u00e1rios cobrindo pelo menos os casos de borda \u00f3bvios (vazio, nulo, limite, valores negativos, duplicados).<\/li>\n<li>H\u00e1 pelo menos uma camada de teste de propriedades para fun\u00e7\u00f5es com l\u00f3gica n\u00e3o trivial.<\/li>\n<li>Execu\u00e7\u00e3o acontece em ambiente isolado quando h\u00e1 acesso a rede, arquivos ou processos externos.<\/li>\n<li>O pipeline de CI bloqueia merge se a cobertura cair abaixo de um limiar definido pela equipe.<\/li>\n<li>Revis\u00e3o humana continua existindo \u2014 o harness reduz risco, n\u00e3o substitui julgamento t\u00e9cnico.<\/li>\n<\/ul>\n<h2>Aprofunde-se na Comunidade Dev&#8217;s AI<\/h2>\n<p>Construir harnesses de teste para c\u00f3digo gerado por IA \u00e9 uma habilidade que se aprimora na pr\u00e1tica, discutindo casos reais com outros desenvolvedores que enfrentam os mesmos desafios. Na <a href=\"https:\/\/adrianosantos.link\/ComunidadeDevAI\" target=\"_blank\" rel=\"noopener\">Comunidade Dev&#8217;s AI<\/a> compartilhamos templates de harness, discutimos ferramentas como Hypothesis, DUnitX, Jest e pytest aplicadas a fluxos com IA, e trocamos experi\u00eancias reais de projetos que j\u00e1 rodam em produ\u00e7\u00e3o com c\u00f3digo assistido por assistentes como Claude Code e Cursor. Se voc\u00ea quer parar de confiar no &#8220;parece certo&#8221; e passar a confiar no &#8220;est\u00e1 provado&#8221;, entre para a comunidade e participe das discuss\u00f5es.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>C\u00f3digo gerado por IA n\u00e3o \u00e9 nem mais nem menos confi\u00e1vel por natureza do que c\u00f3digo escrito por um humano \u2014 mas carrega um tipo espec\u00edfico de risco: a apar\u00eancia de corre\u00e7\u00e3o sem a garantia de corre\u00e7\u00e3o. Um harness de testes bem constru\u00eddo neutraliza esse risco transformando a confian\u00e7a subjetiva (&#8220;parece bom&#8221;) em verifica\u00e7\u00e3o objetiva (&#8220;passou em N casos, N propriedades e rodou isolado sem efeitos colaterais&#8221;).<\/p>\n<p>A boa not\u00edcia \u00e9 que as ferramentas para isso j\u00e1 existem e s\u00e3o maduras, independentemente da linguagem que voc\u00ea usa. O trabalho real est\u00e1 em disciplina: isolar o c\u00f3digo gerado atr\u00e1s de contratos, escrever os casos de borda que a IA n\u00e3o pensou, adicionar testes de propriedades para as invariantes que realmente importam, e automatizar tudo isso no pipeline. Feito isso, voc\u00ea pode aproveitar a velocidade da gera\u00e7\u00e3o assistida por IA sem herdar seus riscos silenciosos.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Imagine a seguinte cena: voc\u00ea pede para um assistente de IA gerar uma fun\u00e7\u00e3o de valida\u00e7\u00e3o de CPF, ou um endpoint de API, ou uma rotina de c\u00e1lculo financeiro. O c\u00f3digo chega r\u00e1pido, bem formatado, com nomes de vari\u00e1veis sensatos e at\u00e9 coment\u00e1rios explicativos. Parece pronto. Voc\u00ea cola no projeto, executa manualmente uma ou duas [&hellip;]<\/p>\n","protected":false},"author":127,"featured_media":1097,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/users\/127"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/comments?post=1053"}],"version-history":[{"count":1,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1053\/revisions"}],"predecessor-version":[{"id":1098,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1053\/revisions\/1098"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media\/1097"}],"wp:attachment":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media?parent=1053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/categories?post=1053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/tags?post=1053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}