Pitch: massa, um gerador de dados de teste brasileiros com dígito verificador de verdade
Quem já testou sistema brasileiro conhece a cena: o formulário recusa o CPF 111.111.111-11, o cadastro de conta não aceita a agência sem DV, e no fim alguém pega um gerador de CPF qualquer e cola linha por linha numa planilha.
Eu fiz o massa para resolver isso: você descreve as colunas e ele devolve a massa de teste em CSV, Excel, JSON ou script SQL, com os documentos passando na validação de dígito verificador.

É gratuito, não tem cadastro e está no ar em https://massa.criando.dev.
O que ele gera
- Documentos: CPF (com a região fiscal da UF, se quiser), CNPJ (inclusive o alfanumérico da IN RFB 2.229/2024), RG de SP, CNH, PIS/PASEP/NIT, título de eleitor e CNS.
- Financeiro: agência e conta corrente com o DV pela regra de cada banco (Banco do Brasil, Santander, Banrisul, Caixa, Bradesco e Itaú) e cartão de crédito com o prefixo da bandeira e o DV de Luhn.
- Campos ligados entre si: e-mail derivado do nome, idade calculada da data de nascimento, cidade dentro da UF, conta que pertence à agência.
- Saídas: CSV, Excel, JSON e
INSERTem SQL padrão ou no dialeto do MySQL, do Oracle e do SQL Server.
Como funciona
Tudo gira em torno de um schema JSON. A interface do site é só um editor visual desse schema:
{
"rows": 3,
"seed": 42,
"ref_date": "2026-10-18",
"fields": [
{ "name": "id", "type": "inteiro", "sequencial": true },
{ "name": "nome", "type": "nome_completo" },
{ "name": "cpf", "type": "cpf", "mask": true },
{ "name": "email", "type": "email", "from": "nome" }
]
}
curl -X POST 'https://massa.criando.dev/api/generate?format=sql&table=cliente' \
-H 'Content-Type: application/json' -d @schema.json
INSERT INTO cliente (id, nome, cpf, email) VALUES (1, 'Rodrigo Moura Rodrigues', '019.936.956-99', 'rodrigo.rodrigues25@exemplo.com');
INSERT INTO cliente (id, nome, cpf, email) VALUES (2, 'Diego Moreira Moreira', '690.051.418-91', 'diego.moreira2@dados.test');
INSERT INTO cliente (id, nome, cpf, email) VALUES (3, 'Camila Moura Souza', '907.815.422-51', 'camila.souza41@dados.test');
Rode de novo e vem exatamente a mesma saída. Isso é de propósito (explico abaixo).
A partir de um CREATE TABLE
Quase sempre a tabela já existe. Dá para colar o CREATE TABLE (Postgres, MySQL, Oracle ou SQL Server, inclusive o que sai do pg_dump, mysqldump ou SSMS) e o massa monta o schema pelo nome das colunas:
CREATE TABLE cliente (
id serial PRIMARY KEY,
nm_cliente varchar(100),
nr_cpf char(11),
dt_nascimento date,
sg_uf char(2),
ds_email varchar(150)
);
nr_cpf vira CPF, dt_nascimento vira data de nascimento, sg_uf vira UF, ds_email vira e-mail ligado ao nome, e o serial vira inteiro sequencial:
id,nm_cliente,nr_cpf,dt_nascimento,sg_uf,ds_email
1,Gabriel Costa Rodrigues,18795649204,2002-02-19,RJ,gabriel.rodrigues30@mail.test
2,Vanessa Vieira Santos,24224201410,1972-12-08,AC,vanessa.santos95@exemplo.com
3,Vitor Moura Souza,04902880652,1956-10-26,TO,vitor.souza5@exemplo.com
Quando a coluna é curta demais para o valor (um e-mail em varchar(20), por exemplo), ele avisa antes, em vez de deixar o INSERT falhar no banco.
As partes que deram mais trabalho
1. Cada banco tem a sua conta
CPF e CNPJ têm regra pública e bem conhecida. Conta corrente não: cada banco tem a sua, e várias dependem da agência. O Itaú, por exemplo, calcula módulo 10 sobre agência e conta juntas:
// dvItau: módulo 10 sobre agência e conta juntas, pesos 2,1,2,1...; produtos
// de dois algarismos somam os algarismos (14 vale 1+4).
func dvItau(ag, c []int) string {
s := 0
for i, v := range append(slices.Clone(ag), c...) {
if i%2 == 0 {
v *= 2
}
s += v/10 + v%10
}
return strconv.Itoa((10 - s%10) % 10)
}
O Santander usa agência + 00 + conta e soma só a unidade de cada produto. A Caixa inclui a operação (001) no cálculo. O Bradesco troca o DV 10 por P e o Banco do Brasil por X.
Eu me impus uma regra: só entra banco com a fórmula publicada e exemplos que eu consiga conferir. Por isso Nubank, Inter, Sicredi e Sicoob ficaram de fora por enquanto. Prefiro faltar banco a gerar uma conta que o sistema testado recuse.
2. Mesma seed, mesma massa
Para um teste ser reproduzível, a massa também precisa ser. Cada linha ganha um gerador aleatório próprio, derivado da seed e do índice da linha:
rng := rand.New(rand.NewPCG(p.seed, uint64(i)))
Na prática: a linha 500 é sempre a mesma, peça você 500 ou 10.000 linhas. O ref_date fixa a data usada para idade e datas, senão a massa mudaria de um dia para o outro.
O cuidado que isso traz: qualquer mudança na forma como um tipo consome o RNG muda a massa de quem já tem um schema salvo. Há testes que travam a sequência de cada tipo justamente para isso não passar despercebido.
3. Nada acumulado em memória
O motor gera linha por linha e entrega para um Sink (CSV, Excel, JSON, SQL). O custo de memória é o de uma linha, não o do arquivo inteiro. Até o Excel sai em streaming.
4. Cartão de crédito tem armadilha
Alguns BINs da Elo começam com 4, que é o prefixo da Visa. Se o gerador sorteia "Visa" e cai num BIN da Elo, o sistema testado vai classificar o cartão como Elo. A geração confere a bandeira pelo prefixo mais longo e sorteia de novo quando isso acontece.
Como está no ar
Escolhi tudo pensando em custo baixo e pouca manutenção:
- Go + templ + HTMX + Tailwind, com a interface embutida num único binário (~17 MB). As páginas de documento funcionam até sem JavaScript.
- Imagem Docker distroless (~23 MB), sem shell e sem root.
- Uma VPS com Coolify: cada push na
maingera o deploy. - Cloudflare na frente, com DNS, proxy e TLS.
- Fluent Bit → Loki → Grafana para os logs. O log registra rota, status, latência e quantas linhas foram geradas, mas nunca o corpo da requisição nem os dados gerados.
- Limite por IP (balde de fichas em memória), já que o uso é anônimo.
Também dá para usar pelo assistente de IA
O massa tem um servidor MCP público em https://massa.criando.dev/mcp. Depois de conectar no Claude Code, Cursor, VS Code ou outro cliente com MCP remoto, dá para pedir:
Use o massa para transformar este CREATE TABLE em INSERTs com 50 linhas.
O assistente chama o mesmo motor do site e recebe o resultado na conversa. Para Excel, recebe um link: o schema vai comprimido na própria URL e o arquivo é gerado no clique, sem nada guardado no servidor.
O que ele não é
- Válido aqui quer dizer "passa no dígito verificador". O massa não consulta cadastro nenhum: não garante que o CPF exista, que a conta esteja ativa ou que o cartão passe num pagamento.
- São dados sintéticos. Como os números são sorteados, um deles pode coincidir com um documento real. É para ambiente de teste, não para cadastro de verdade.
- Gera uma tabela por vez. Importar várias tabelas com chave estrangeira está no roadmap.
- O código ainda não é aberto.
Queria a opinião de vocês
- Que tipo de dado falta no seu dia a dia de testes? Já tenho anotados placa de veículo e CEP coerente com a UF.
- Alguém conhece a regra pública de DV de conta do Nubank, do Inter ou do Sicoob?
- O que vocês fariam diferente na infraestrutura?
Fonte: https://massa.criando.dev