Por Devy · Categoría: AI Dev Tools — Open Source
Peça a um agente de codificação para “adicionar testes unitários a este projeto” e você acabou de entregar a ele um problema muito mais ambíguo do que parece. Qual código precisa de testes? Qual framework o repositório usa? Onde vivem os testes existentes? Quais dependências precisam ser simuladas? Quais casos realmente importam? E como sabemos que os novos testes verificam comportamento real em vez de simplesmente passar?
A Microsoft decidiu que esse problema merecia um agente dedicado.
code-testing-generator é um agente open source e poliglota para geração de testes unitários. Não tenta implementar features, corrigir tickets, refatorar o projeto e atualizar a documentação ao mesmo tempo. Tem uma missão muito mais estreita:
encontrar o que precisa de testes, entender como esse repositório é testado, escrevê-los e demonstrar que funcionam.
E justamente por isso é interessante.
A obsessão atual é construir agentes cada vez mais gerais. A Microsoft está explorando o caminho oposto: uma responsabilidade estreita, ferramentas específicas e um resultado que pode ser verificado automaticamente.
Documentação oficial de code-testing-generator
Repositório microsoft/testfx
Não é simplesmente um prompt para “gerar testes”
A Microsoft descreve code-testing-generator como um agente coordenador que executa um pipeline completo.
O fluxo básico é:
Research
↓
Plan
↓
Implement
↓
Build
↓
Test
↓
Fix
↓
Lint
↓
Validate
E aqui aparece a primeira diferença importante em relação a pedir testes a um chatbot.
Antes de escrever qualquer coisa, o sistema investiga o repositório.
Precisa descobrir coisas como:
- que linguagem está usando;
- qual é o framework de testing;
- como o projeto está organizado;
- onde vivem os testes existentes;
- que convenções seguem;
- que código ainda precisa de cobertura;
- que dependências externas deveriam ser isoladas;
- como executar corretamente build e testes.
Depois constrói um plano.
Somente então começa a gerar código. (GitHub)
Na verdade não é um agente: é um pequeno time
O nome code-testing-generator pode levar a pensar que há um único agente escrevendo testes.
A implementação é bem mais interessante.
A Microsoft divide o trabalho entre agentes especializados:
code-testing-generator
│
├── code-testing-researcher
├── code-testing-planner
├── code-testing-implementer
├── code-testing-builder
├── code-testing-tester
├── code-testing-fixer
└── code-testing-linter
O generator coordena o pipeline.
O researcher entende o codebase.
O planner decide quais testes implementar.
O implementer os escreve.
O builder verifica que o projeto compile.
O tester executa os testes.
O fixer tenta corrigir erros.
E o linter deixa o código consistente com as convenções do projeto. (GitHub)
Isso importa porque mostra um padrão bem útil para qualquer um que esteja construindo agentes internos.
Em vez de:
SUPER AGENT
│
├── entende o repo
├── projeta testes
├── escreve código
├── compila
├── depura
├── executa testes
└── decide se terminou
A Microsoft separa responsabilidades e converte cada fase em um passo explícito.
Você não precisa que um único prompt faça mágica.
Você precisa de um workflow que possa verificar seu próprio trabalho.
O loop que torna testing perfeito para agentes
Há tarefas onde avaliar a resposta de um agente é difícil.
Peça:
Melhore a arquitetura deste projeto.
Pode produzir 2.000 linhas de mudanças e você ainda precisa de um senior engineer para determinar se realmente melhorou algo.
Testing tem uma propriedade completamente distinta.
Podemos fechar o loop:
analisar
↓
gerar teste
↓
compilar
↓
executar
↓
funciona?
├── não → corrigir
└── sim → validar
O ambiente produz feedback automaticamente.
Isso não significa que um teste que passa seja necessariamente um bom teste. A Microsoft reconhece explicitamente esse problema: o agente também revisa as assertions, os cenários solicitados e se o runner normal do repositório realmente descobre os novos testes. (Microsoft for Developers)
A distinção é fundamental.
Um agente poderia gerar isso:
expect(true).toBe(true)
O teste passa.
Não verifica absolutamente nada.
A métrica útil não pode ser simplesmente:
testes verdes
Tem que se aproximar mais de:
testes verdes
+
comportamento relevante verificado
+
assertions significativas
+
integração correta com o test suite existente
O que testa — e o que não testa —
code-testing-generator é focado especificamente em testes unitários.
A Microsoft diz que o agente tenta isolar o código sob teste e simular serviços externos ou outras dependências quando apropriado. (Microsoft for Developers)
Por enquanto ficam fora do escopo:
- integration tests;
- end-to-end tests;
- browser tests;
- performance tests.
Isso não é uma deficiência acidental.
Faz parte da ideia.
Os testes unitários fornecem um ambiente relativamente controlado onde o agente pode gerar uma hipótese sobre comportamento e verificá-la rapidamente.
Quanto mais se afasta desse ambiente — browser state, serviços externos, infraestrutura, timing distribuído — mais difícil se torna fechar automaticamente o loop.
Como testá-lo
Há um esclarecimento importante antes de começar: code-testing-generator não é distribuído hoje como uma aplicação independente que você instala com um npm install -g code-testing-generator.
Faz parte do tooling de testing da Microsoft e está disponível como agente/skill dentro do ecossistema dotnet-test. A implementação e as referências podem ser inspecionadas nos repositórios públicos da Microsoft. (GitHub)
Os requisitos documentados incluem:
VS Code
GitHub Copilot
um projeto com build/test configurado
um framework de testing instalado ou instalável
(GitHub)
Uma vez que o agente estiver disponível em seu ambiente, o workflow pode começar com algo tão simples quanto pedir:
Generate unit tests for this project.
Mas há uma forma melhor de usá-lo.
Por exemplo:
Generate Jest unit tests for the authentication service.
Focus on code that doesn't currently have test coverage.
Ou:
Generate unit tests for the payment calculation module.
Do not modify production code.
Especificar framework ou escopo reduz decisões desnecessárias e ajuda o agente a se concentrar na parte do codebase que você realmente quer cobrir.
Passo 1: discovery
A primeira fase não deveria produzir código.
O researcher inspeciona o projeto e tenta entender como funciona.
Em um repo real poderia descobrir algo parecido com:
src/
services/
invoice.ts
pricing.ts
customer.ts
tests/
invoice.test.ts
customer.test.ts
```Há testes para `invoice` e `customer`.
`pricing.ts` não tem nenhum.
Mas isso ainda não significa automaticamente:
escrevi `pricing.test.ts`.
Primeiro você precisa ler os testes existentes e aprender as convenções do projeto.
Talvez encontre:
describe(“InvoiceService”, () => {
…
})
Mocks com uma biblioteca determinada.
Factories para criar fixtures.
Helpers compartilhados.
Uma estrutura concreta para nomes.
O objetivo é que o agente não invente um mini-framework de testing novo dentro do seu repo.
## **Passo 2: planejamento**
Depois da pesquisa aparece um artefato especialmente útil:
.testagent/plan.md
A documentação da Microsoft faz referência explícita a este plano durante troubleshooting. ([GitHub](https://github.com/microsoft/testfx/blob/f8340abd9b5e6693d656e20b1ac8a47e5db1c514/.agents/skills/code-testing-agent/SKILL.md?utm_source=chatgpt.com))
Esse arquivo importa porque cria um ponto de revisão **antes** de o agente gerar uma montanha de código.
Você pode inspecionar:
quais arquivos ele pensa testar
quais cenários encontrou
quais mocks precisa
quais edge cases identificou
qual estrutura propõe
Este padrão merece ser copiado em outros agentes.
Não:
prompt → 37 arquivos modificados
Mas:
prompt
↓
pesquisa
↓
plano revisável
↓
implementação
O plano se torna uma fronteira entre raciocínio e ação.
## **Passo 3: implementação**
O implementer pega uma fase do plano e escreve os testes.
Microsoft projetou o sistema como polyglot: a documentação do repo descreve o researcher, planner, implementer, builder, tester e linter como agentes capazes de trabalhar com diferentes linguagens. Também existem extensões específicas para ajudar a detectar frameworks e convenções conforme o ecossistema. ([GitHub](https://github.com/microsoft/testfx/blob/f8340abd9b5e6693d656e20b1ac8a47e5db1c514/AGENTS.md?utm_source=chatgpt.com))
Por exemplo, para .NET pode detectar frameworks como:
MSTest
xUnit
NUnit
TUnit
A mesma filosofia se aplica a outras stacks: entender primeiro o que o repo usa em vez de impor uma ferramenta.
## **Passo 4: build**
Aqui começa a parte que separa geração de código de **engineering verificável**.
Depois de escrever os testes, o agente compila.
Se falhar:
generated tests
↓
build
↓
FAILURE
↓
code-testing-fixer
↓
build
Microsoft até recomenda que durante a implementação se compile apenas o projeto de testes correspondente para acelerar o loop, e fazer um build completo do workspace ao final. ([GitHub](https://github.com/microsoft/testfx/blob/f8340abd9b5e6693d656e20b1ac8a47e5db1c514/.agents/skills/code-testing-agent/SKILL.md?utm_source=chatgpt.com))
É um detalhe pequeno, mas demonstra que o workflow foi pensado para repos reais, onde recompilar uma solução inteira depois de cada mudança pode ser muito caro.
## **Passo 5: executar os testes**
Uma vez que compila, chega a prova real.
O tester executa o suite.
Se algo falhar, há uma regra particularmente boa na documentação:
**não assumir que o código de produção está errado.**
Microsoft avisa que muitas falhas em testes gerados vêm de expected values incorretos nas assertions.
O workflow recomendado é:
ler output real
↓
ler produção
↓
entender comportamento correto
↓
corrigir assertion
Não:
teste falha
↓
mudança produção até que passe
([GitHub](https://github.com/microsoft/testfx/blob/f8340abd9b5e6693d656e20b1ac8a47e5db1c514/.agents/skills/code-testing-agent/SKILL.md?utm_source=chatgpt.com))
Parece óbvio quando escrevemos assim.
Para um agente autônomo, não é.
## **E nunca esconder o problema com Skip**
A documentação adiciona outra regra que deveria estar em qualquer agente de testing:
**não marque testes com `Ignore` ou `Skip` simplesmente para conseguir um suite verde.** ([GitHub](https://github.com/microsoft/testfx/blob/f8340abd9b5e6693d656e20b1ac8a47e5db1c514/.agents/skills/code-testing-agent/SKILL.md?utm_source=chatgpt.com))
Esse tipo de guardrail é precisamente o que torna interessante um agente especializado.
Um agente geral recebe:
arregle os testes.
E tem centenas de maneiras de produzir aparentemente o resultado solicitado.
Um agente especializado pode ter regras muito mais rigorosas sobre o que constitui uma solução válida.
## **Caso de uso 1: o módulo novo que saiu sem testes**
Imagine que uma equipe acabou de adicionar:
src/billing/discount-engine.ts
Tem vários branches:
cliente novo
cliente premium
cupom expirado
desconto máximo
combinação de promoções
A feature funciona, mas o sprint terminou e ninguém escreveu o suite completo.
Este é praticamente o caso ideal.
Você dá scope ao agente:
Generate unit tests for discount-engine.ts.
Use the existing test conventions.
Do not modify production code.
O agente pode estudar os testes vizinhos, identificar branches, planejar cenários, gerar casos, executar o suite e corrigir seus próprios erros.
O humano revisa o resultado final.
Não precisou delegar a compreensão completa do sistema.
Delegou uma tarefa estreita com um critério de aceitação claro.
## **Caso de uso 2: um codebase antigo com cobertura desigual**
O segundo cenário é provavelmente mais valioso.
Você tem um repo de cinco anos.
Algumas áreas têm testes excelentes.
Outras quase nenhum.
Pedir a um agente:
aumente a cobertura do projeto
é perigosamente aberto.
Mas você pode dar um módulo concreto e deixar que primeiro faça discovery.
Por exemplo:
Analyze src/payments for missing unit-test coverage.
Create a test plan first.
Then generate and validate tests using the project’s existing framework and conventions.
Aí o agente funciona mais como **test engineer assistido** do que como gerador de snippets.
E o plano prévio permite que você o pare antes de tocar código se entendeu mal a arquitetura.
## **Caso de uso 3: o PR gerado por outro agente**
Há um cenário ainda mais interessante.
Claude Code implementa uma feature.
Depois, em vez de pedir ao mesmo agente:
agora escreve seus próprios testes,
você poderia enviar o diff para um agente especializado.
coding agent
↓
implementation
↓
testing agent
↓
tests
↓
build + execution
↓
human review
Isso introduz uma certa separação de responsabilidades.
O agente que produziu a implementação não é necessariamente quem decide como demonstrar que funciona.
Não é independência perfeita —ambos podem usar modelos similares—, mas arquitetonicamente é muito mais saudável do que um único agente sendo simultaneamente autor, testador e juiz do seu próprio trabalho.
## **A lição mais importante não é sobre unit testing**
`code-testing-generator` é interessante pelo que faz.
Mas me parece ainda mais interessante por **como está projetado**.
Estamos construindo muitos agentes assim:
Agente de Engineering
Pode:
- escrever código
- fazer reviews
- fazer deploy
- investigar bugs
- modificar infraestrutura
- consultar produção
- atualizar Jira
- escrever documentação
- abrir PRs
- executar comandos
Isso soa impressionante em uma demo.
Também cria um sistema com enorme superfície de permissões e uma definição bastante vaga de sucesso.
O padrão da Microsoft vai na direção contrária:
responsabilidade estreita
+
tools específicas
+
workflow estruturado
+
feedback automático
+
critério verificável
Esse design tem uma propriedade que provavelmente vai importar muito quando começarmos a colocar agentes em produção:
**podemos saber quando terminou bem.**
## **Os melhores agentes talvez sejam chatos**
Há uma tentação compreensível de imaginar o futuro como um swarm de agentes autônomos administrando toda a organização.
Podemos chegar lá.
Mas boa parte do valor imediato provavelmente venha de algo bem menos cinematográfico:
agente que escreve testes
agente que atualiza dependências
agente que classifica bugs
agente que revisa migrations
agente que reproduz erros
agente que atualiza documentação
Cada um com acesso apenas às ferramentas que precisa.
Cada um com um output definido.
E, quando possível, cada um com uma forma automática de demonstrar que fez corretamente seu trabalho.
`code-testing-generator` é um bom exemplo porque testing tem esse loop incorporado de fábrica:
**gerar → executar → observar → corrigir → verificar.**
Não elimina o code review. Tampouco demonstra que os testes gerados sejam necessariamente os testes que um senior engineer teria escrito.
O que faz é muito mais concreto: automatiza uma tarefa custosa e repetível sem pretender que o agente seja capaz de fazer absolutamente tudo.
E talvez essa seja uma arquitetura muito mais interessante para a próxima geração de agentes.
---
**Fontes**
* [From generated code to trusted code with a unit-test agent — Microsoft .NET Blog](https://devblogs.microsoft.com/dotnet/polyglot-unit-testing-agent/?utm_source=chatgpt.com)
* [microsoft/testfx — GitHub](https://github.com/microsoft/testfx?utm_source=chatgpt.com)
* [Code Testing Generation Skill — GitHub](https://github.com/microsoft/testfx/blob/f8340abd9b5e6693d656e20b1ac8a47e5db1c514/.agents/skills/code-testing-agent/SKILL.md?utm_source=chatgpt.com)
* [AGENTS.md de microsoft/testfx — GitHub](https://github.com/microsoft/testfx/blob/f8340abd9b5e6693d656e20b1ac8a47e5db1c514/AGENTS.md?utm_source=chatgpt.com)
