Como Gerar Testes Automatizados com Claude Code (Jest, Pytest, Vitest)
A maioria dos projetos tem uma cobertura de testes muito abaixo do ideal. Nao porque os devs nao sabem que testes sao importantes -- sabem. O problema e que escrever testes e tedioso, leva tempo, e quando o prazo aperta, testes sao os primeiros a serem cortados.
O Claude Code resolve esse problema. Ele analisa seu codigo existente, identifica caminhos criticos, edge cases e pontos de falha, e gera suites de testes completas em segundos. Nao testes genericos -- testes que realmente cobrem a logica do seu codigo.
Neste guia, voce vai ver como gerar testes com os frameworks mais populares (Jest, Vitest, Pytest, Cypress), como ir de 0 a 80% de coverage, e como usar TDD com Claude Code para escrever codigo melhor desde o inicio.
1. Por que usar IA para gerar testes
Gerar testes com IA nao e "preguica de dev". E uma decisao pragmatica. Veja os numeros:
- Tempo: escrever testes manualmente leva em media 30-50% do tempo total de desenvolvimento. Com Claude Code, cai para 5-10%
- Cobertura: devs tendem a testar o "caminho feliz" e esquecer edge cases. O Claude Code identifica cenarios que voce nao pensou
- Consistencia: testes gerados seguem o mesmo padrao -- naming conventions, estrutura, assertions. Sem variacao de estilo entre devs
- Legacy code: adicionar testes a codigo existente sem testes e o caso de uso mais poderoso. O Claude Code le a funcao e gera cobertura completa
Dado real: em projetos onde usamos Claude Code para gerar testes de codigo legacy, a cobertura foi de 12% para 78% em um unico dia de trabalho. Manualmente, isso levaria semanas.
O ponto crucial: testes gerados por IA sao um ponto de partida excelente, nao o produto final. Voce sempre deve revisar para garantir que os testes validam comportamento, nao apenas que o codigo roda sem erro.
2. Testes unitarios com Jest e Vitest
Gerando testes para funcao existente
Digamos que voce tem essa funcao sem testes:
// src/utils/price.ts
export function calculateDiscount(price: number, coupon: string): number {
if (price <= 0) throw new Error('Price must be positive');
const coupons: Record<string, number> = {
'WELCOME10': 0.10,
'BLACKFRIDAY': 0.30,
'VIP50': 0.50,
};
const discount = coupons[coupon.toUpperCase()];
if (!discount) return price;
const final = price * (1 - discount);
return Math.round(final * 100) / 100;
}
O Claude Code gera:
// src/utils/price.test.ts
import { describe, it, expect } from 'vitest';
import { calculateDiscount } from './price';
describe('calculateDiscount', () => {
// Caminho feliz
it('aplica desconto WELCOME10 corretamente', () => {
expect(calculateDiscount(100, 'WELCOME10')).toBe(90);
});
it('aplica desconto BLACKFRIDAY corretamente', () => {
expect(calculateDiscount(200, 'BLACKFRIDAY')).toBe(140);
});
it('aplica desconto VIP50 corretamente', () => {
expect(calculateDiscount(100, 'VIP50')).toBe(50);
});
// Case insensitive
it('aceita cupom em lowercase', () => {
expect(calculateDiscount(100, 'welcome10')).toBe(90);
});
it('aceita cupom em mixed case', () => {
expect(calculateDiscount(100, 'Welcome10')).toBe(90);
});
// Cupom invalido
it('retorna preco original para cupom invalido', () => {
expect(calculateDiscount(100, 'INVALIDO')).toBe(100);
});
it('retorna preco original para cupom vazio', () => {
expect(calculateDiscount(100, '')).toBe(100);
});
// Edge cases de preco
it('arredonda para 2 casas decimais', () => {
expect(calculateDiscount(99.99, 'WELCOME10')).toBe(89.99);
});
it('funciona com precos muito pequenos', () => {
expect(calculateDiscount(0.01, 'VIP50')).toBe(0.01);
});
// Erros
it('lanca erro para preco zero', () => {
expect(() => calculateDiscount(0, 'WELCOME10')).toThrow('Price must be positive');
});
it('lanca erro para preco negativo', () => {
expect(() => calculateDiscount(-10, 'WELCOME10')).toThrow('Price must be positive');
});
});
Note como o Claude Code identificou automaticamente: case sensitivity do cupom, arredondamento de decimais, preco zero vs negativo. Esses sao edge cases que muitos devs esquecem de testar.
Gerando testes para modulo inteiro
O Claude Code varre a pasta, identifica quais arquivos ja tem testes, e gera apenas os que faltam. Ele respeita o padrao do projeto -- se seus testes existentes usam describe/it, ele segue o mesmo estilo.
3. Testes com Pytest (Python)
Para projetos Python, o Claude Code gera testes com Pytest usando fixtures, parametrize e mocking.
# src/services/user_service.py
class UserService:
def __init__(self, db, email_client):
self.db = db
self.email_client = email_client
def register(self, email: str, password: str) -> dict:
if not email or '@' not in email:
raise ValueError('Email invalido')
if len(password) < 8:
raise ValueError('Senha deve ter no minimo 8 caracteres')
existing = self.db.find_user_by_email(email)
if existing:
raise ValueError('Email ja cadastrado')
user = self.db.create_user(email=email, password=password)
self.email_client.send_welcome(email)
return user
# tests/test_user_service.py
import pytest
from unittest.mock import MagicMock, patch
from src.services.user_service import UserService
@pytest.fixture
def mock_db():
db = MagicMock()
db.find_user_by_email.return_value = None
db.create_user.return_value = {'id': 1, 'email': 'user@test.com'}
return db
@pytest.fixture
def mock_email():
return MagicMock()
@pytest.fixture
def service(mock_db, mock_email):
return UserService(db=mock_db, email_client=mock_email)
class TestUserRegister:
def test_registro_sucesso(self, service, mock_db, mock_email):
result = service.register('user@test.com', 'senha12345')
assert result['id'] == 1
mock_db.create_user.assert_called_once_with(
email='user@test.com', password='senha12345'
)
mock_email.send_welcome.assert_called_once_with('user@test.com')
@pytest.mark.parametrize('email', ['', 'invalido', 'sem-arroba.com', None])
def test_email_invalido(self, service, email):
with pytest.raises(ValueError, match='Email invalido'):
service.register(email, 'senha12345')
@pytest.mark.parametrize('password', ['', '1234567', 'abcdefg'])
def test_senha_curta(self, service, password):
with pytest.raises(ValueError, match='Senha deve ter no minimo 8'):
service.register('user@test.com', password)
def test_email_duplicado(self, service, mock_db):
mock_db.find_user_by_email.return_value = {'id': 99}
with pytest.raises(ValueError, match='Email ja cadastrado'):
service.register('user@test.com', 'senha12345')
def test_nao_envia_email_se_registro_falhar(self, service, mock_db, mock_email):
mock_db.create_user.side_effect = Exception('DB error')
with pytest.raises(Exception):
service.register('user@test.com', 'senha12345')
mock_email.send_welcome.assert_not_called()
O Claude Code usou @pytest.mark.parametrize para evitar duplicacao de testes, fixtures para injecao de dependencia, e ate testou o cenario de falha no banco -- verificando que o email de boas-vindas nao e enviado se o registro falhar.
Isso ai em cima? Skills fazem automaticamente.
Cada tecnica que voce esta lendo pode ser transformada em skill — um comando que o Claude executa perfeitamente, toda vez. O Mega Bundle tem 748+ skills prontas para marketing, dev, SEO, copy e mais.
Ver Skills Prontas — R$194. Testes de integracao
Testes de integracao verificam se multiplos modulos funcionam juntos. O Claude Code gera testes que levantam dependencias reais (banco de dados, APIs) ou usam containers de teste.
// tests/integration/users.test.ts
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import request from 'supertest';
import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { createApp } from '../../src/app';
import { migrate } from '../../src/db/migrate';
let container: any;
let app: any;
beforeAll(async () => {
container = await new PostgreSqlContainer().start();
process.env.DATABASE_URL = container.getConnectionUri();
await migrate();
app = createApp();
}, 30000);
afterAll(async () => {
await container.stop();
});
describe('POST /api/users', () => {
it('cria usuario com dados validos', async () => {
const res = await request(app)
.post('/api/users')
.send({ email: 'test@example.com', password: 'senha12345' });
expect(res.status).toBe(201);
expect(res.body).toHaveProperty('id');
expect(res.body.email).toBe('test@example.com');
});
it('retorna 409 para email duplicado', async () => {
await request(app)
.post('/api/users')
.send({ email: 'dup@example.com', password: 'senha12345' });
const res = await request(app)
.post('/api/users')
.send({ email: 'dup@example.com', password: 'senha12345' });
expect(res.status).toBe(409);
});
it('retorna 400 para email invalido', async () => {
const res = await request(app)
.post('/api/users')
.send({ email: 'invalido', password: 'senha12345' });
expect(res.status).toBe(400);
});
});
5. Testes e2e com Cypress e Playwright
Para testes end-to-end, o Claude Code gera scripts que simulam o usuario real navegando pela aplicacao.
// tests/e2e/checkout.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Fluxo de Checkout', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/login');
await page.fill('[data-testid="email"]', 'user@test.com');
await page.fill('[data-testid="password"]', 'senha12345');
await page.click('[data-testid="login-btn"]');
await expect(page).toHaveURL('/dashboard');
});
test('completa checkout com sucesso', async ({ page }) => {
// Adicionar produto
await page.goto('/products');
await page.click('[data-testid="product-1"] .add-to-cart');
await expect(page.locator('.cart-count')).toHaveText('1');
// Ir para carrinho
await page.click('[data-testid="cart-icon"]');
await expect(page).toHaveURL('/cart');
await expect(page.locator('.cart-item')).toHaveCount(1);
// Pagamento
await page.click('[data-testid="checkout-btn"]');
await page.fill('[data-testid="card-number"]', '4242424242424242');
await page.fill('[data-testid="card-expiry"]', '12/28');
await page.fill('[data-testid="card-cvc"]', '123');
await page.click('[data-testid="pay-btn"]');
// Confirmacao
await expect(page).toHaveURL(/\/order\/\d+/);
await expect(page.locator('.order-status')).toHaveText('Pedido confirmado');
});
});
6. Coverage analysis: de 0 a 80%
O Claude Code nao apenas gera testes -- ele analisa sua cobertura atual e identifica exatamente onde estao os gaps.
[Executando: npx vitest run --coverage]
[Coverage atual: 34%]
Arquivos com menor cobertura:
src/services/payment.ts -- 8%
src/utils/validation.ts -- 12%
src/middleware/auth.ts -- 15%
Gerando testes para esses 3 arquivos...
O workflow recomendado:
- Rode
coveragepara ver o estado atual - Peca ao Claude Code para focar nos arquivos com menor cobertura
- Revise os testes gerados
- Rode coverage novamente para verificar o impacto
- Repita ate atingir a meta
7. TDD com Claude Code
Test-Driven Development com Claude Code inverte o fluxo tradicional de geracao de testes. Em vez de "tenho codigo, gere testes", voce faz "tenho requisitos, gere testes, depois implemente".
O ciclo Red-Green-Refactor com IA
> preciso de uma funcao que valide CPF. gere os testes primeiro, sem implementar a funcao. cenarios: CPF valido, invalido, formatado, sem formatacao, sequencias repetidas
# Passo 2: GREEN -- implemente o minimo
> agora implemente a funcao validateCPF que faz todos os testes passarem
# Passo 3: REFACTOR -- melhore o codigo
> refatore a implementacao para ser mais legivel e performatica, sem quebrar os testes
Essa abordagem garante que seus testes refletem requisitos, nao a implementacao. Se voce gerar testes depois do codigo, ha um risco de os testes serem "contaminados" pela implementacao -- testando como o codigo funciona, nao o que ele deveria fazer.
8. Skills de testes prontas
O pacote de skills Dev inclui skills especializadas para geracao de testes:
| Skill | O que faz |
|---|---|
/test-unit | Gera testes unitarios para arquivo ou funcao especifica |
/test-integration | Gera testes de integracao com setup de banco e APIs |
/test-e2e | Gera testes end-to-end com Playwright ou Cypress |
/test-coverage | Analisa coverage e gera testes para gaps |
/test-api | Gera testes para endpoints REST/GraphQL |
/tdd | Inicia ciclo TDD: gera testes a partir de requisitos |
Perguntas frequentes
Sim. Esse e um dos melhores casos de uso. Voce aponta o Claude Code para um arquivo ou modulo sem testes e pede para gerar cobertura completa. Ele analisa a funcao, identifica inputs, outputs, edge cases e gera testes unitarios cobrindo o caminho feliz, erros esperados e casos limite. Funciona com Jest, Vitest, Pytest, Go testing e qualquer outro framework.
Os testes gerados pelo Claude Code sao um excelente ponto de partida. Eles cobrem os cenarios principais e edge cases mais comuns. Porem, voce deve sempre revisar para garantir que os testes validam o comportamento correto (nao apenas que o codigo roda sem erro). Testes que apenas verificam que a funcao retorna algo, sem validar o que retorna, dao falsa sensacao de seguranca.
Sim. O workflow ideal e: voce descreve o comportamento desejado, o Claude Code gera os testes primeiro (que vao falhar), depois voce pede para implementar o codigo que faz os testes passarem. Isso garante que os testes refletem os requisitos, nao a implementacao. O Claude Code entende o ciclo red-green-refactor e gera testes antes do codigo quando solicitado.