Dados Fictícios para Testes de Software (2026): Ferramentas, Estratégias e LGPD
Dado fictício é a base de qualquer teste automatizado que não viola LGPD. Este guia cobre o porquê (lei + prática), ferramentas por linguagem, uso de factories e seed determinístico, cenários realistas e estratégias para manter ambiente de staging limpo e útil.
Por Vitor Morais
Fundador do MochaLabz ·
Gere CPFs em lote
Quantidade, formato e download em CSV — tudo no navegador, sem cadastro.
Usar gerador →Dado fictício é pilar invisível de todo software que leva qualidade a sério: sem ele, seus testes automatizados não existem, sua demo tem dados de clientes reais expostos e seu staging vira risco de LGPD. O investimento em geração de dados fictícios é baixo (bibliotecas prontas, 5-10 linhas de código), o retorno é alto (testes confiáveis, conformidade, sanidade mental).
Este guia cobre os motivos práticos e legais para usar dados fictícios, bibliotecas padrão em JavaScript, Python, Ruby e Java, uso de factories para dados coerentes, seed determinístico para testes reproduzíveis em CI e estratégias para evitar que dados fictícios “vazem” para produção.
Por que dados fictícios: três razões fundamentais
1. LGPD (obrigatório)
Dado pessoal (CPF, nome, e-mail, telefone) em testes sem base legal viola a LGPD. Artigos 7 e 11 exigem finalidade específica. Uso para testes não se enquadra em nenhuma das 10 bases legais se o titular não consentiu. Multas vão até 2% do faturamento. Desde 2023, ANPD aplica multas reais. Dados fictícios eliminam o problema — documento matematicamente válido sem ser de pessoa real não é dado pessoal.
2. Vazamento de staging
Cenários reais: credencial de banco staging em commit do GitHub; backup acidental exposto em bucket S3 público; servidor de staging sem firewall. Se o banco tem CPFs reais, é vazamento. Se tem só fictícios, é zero problema.
3. Controle de cenários de teste
Teste precisa de dados previsíveis: “usuário com 3 pedidos vencidos”, “e-mail com acento no nome”, “data no ano 2038”. Dados reais têm distribuição natural que raramente cobre todos esses casos. Dados fictícios deixam você modelar cenários exatos.
Atenção
Ferramentas por linguagem
JavaScript / TypeScript: Faker-js
npm install -D @faker-js/fakerimport { faker } from "@faker-js/faker/locale/pt_BR";
// Pessoa completa
const pessoa = {
nome: faker.person.fullName(),
cpf: faker.br.cpf(),
email: faker.internet.email(),
telefone: faker.phone.number(),
dataNascimento: faker.date.birthdate(),
endereco: {
rua: faker.location.street(),
numero: faker.number.int({ min: 1, max: 9999 }),
bairro: faker.location.secondaryAddress(),
cidade: faker.location.city(),
estado: faker.location.state({ abbreviated: true }),
cep: faker.location.zipCode("#####-###"),
},
empresa: {
nome: faker.company.name(),
cnpj: faker.br.cnpj(),
},
};
// Array de 1000 pessoas
const pessoas = Array.from({ length: 1000 }, () => ({
nome: faker.person.fullName(),
cpf: faker.br.cpf(),
email: faker.internet.email(),
}));Python: Faker
pip install fakerfrom faker import Faker
fake = Faker("pt_BR")
# Pessoa completa
pessoa = {
"nome": fake.name(),
"cpf": fake.cpf(),
"email": fake.email(),
"telefone": fake.phone_number(),
"data_nascimento": fake.date_of_birth(),
"endereco": {
"rua": fake.street_name(),
"numero": fake.random_int(1, 9999),
"bairro": fake.bairro(),
"cidade": fake.city(),
"estado": fake.estado_sigla(),
"cep": fake.postcode(),
},
}
# Lista de 1000
pessoas = [
{
"nome": fake.name(),
"cpf": fake.cpf(),
"email": fake.email(),
}
for _ in range(1000)
]Ruby: Faker gem
# Gemfile
gem "faker"
gem "factory_bot_rails"
# Uso
require "faker"
Faker::Config.locale = :"pt-BR"
Faker::Name.name # "João da Silva"
Faker::CPF.number # "14339725095"
Faker::CNPJ.number # "62030781000162"
Faker::Internet.email # "joao@exemplo.com"
Faker::PhoneNumber.cell_phone # "(11) 98765-4321"
Faker::Address.city # "São Paulo"
Faker::Company.name # "Empresa X LTDA"Java: JavaFaker
// Maven / Gradle
// implementation 'com.github.javafaker:javafaker:1.0.2'
import com.github.javafaker.Faker;
import java.util.Locale;
Faker faker = new Faker(new Locale("pt-BR"));
String nome = faker.name().fullName();
String cpf = faker.cpf().valid();
String email = faker.internet().emailAddress();
String telefone = faker.phoneNumber().cellPhone();Go: gofakeit
// go get github.com/brianvoe/gofakeit/v6
import "github.com/brianvoe/gofakeit/v6"
type Pessoa struct {
Nome string
Email string
Telefone string
}
p := Pessoa{
Nome: gofakeit.Name(),
Email: gofakeit.Email(),
Telefone: gofakeit.Phone(),
}Factories: dados coerentes entre entidades
Em aplicações com relacionamentos (Cliente → Pedido → Item), factories garantem consistência:
Exemplo em JavaScript/TypeScript
import { faker } from "@faker-js/faker/locale/pt_BR";
// factory: cliente
export function criarCliente() {
return {
id: faker.string.uuid(),
nome: faker.person.fullName(),
email: faker.internet.email(),
cpf: faker.br.cpf(),
criadoEm: faker.date.past(),
};
}
// factory: pedido (requer clientId)
export function criarPedido(clienteId: string) {
return {
id: faker.string.uuid(),
clienteId,
valor: Number(faker.commerce.price({ min: 50, max: 5000 })),
status: faker.helpers.arrayElement(["novo", "pago", "enviado", "entregue"]),
criadoEm: faker.date.recent(),
};
}
// factory: cliente com N pedidos
export function criarClienteComPedidos(numeroPedidos = 3) {
const cliente = criarCliente();
const pedidos = Array.from({ length: numeroPedidos }, () =>
criarPedido(cliente.id),
);
return { cliente, pedidos };
}
// Uso
const { cliente, pedidos } = criarClienteComPedidos(5);FactoryBot em Ruby (padrão Rails)
# spec/factories/clientes.rb
FactoryBot.define do
factory :cliente do
nome { Faker::Name.name }
email { Faker::Internet.email }
cpf { Faker::CPF.number }
trait :com_pedidos do
after(:create) do |cliente|
create_list(:pedido, 3, cliente: cliente)
end
end
end
factory :pedido do
association :cliente
valor { Faker::Commerce.price(range: 50.0..5000.0) }
status { Pedido.statuses.keys.sample }
end
end
# Uso em teste
cliente = create(:cliente, :com_pedidos)
# Cria cliente + 3 pedidos associadosSeed determinístico para CI reprodutível
Testes que geram dados aleatórios são pesadelos para debugar. Solução: seed fixo.
JavaScript / TypeScript
import { faker } from "@faker-js/faker";
// Em setup de testes (vitest/jest)
beforeAll(() => {
faker.seed(42);
});
// Cada chamada produz o mesmo valor entre execuções
faker.person.firstName(); // sempre "João" (exemplo)
faker.person.firstName(); // sempre "Maria"Python
from faker import Faker
fake = Faker("pt_BR")
Faker.seed(42)
# Agora gera sequência determinística
fake.name() # sempre mesmo nome
fake.name() # sempre mesmo próximoDica
Seed de banco: estratégias
Para desenvolvimento local
// db/seed.ts
import { db } from "./db";
import { criarCliente, criarPedido } from "./factories";
async function seed() {
if (process.env.NODE_ENV === "production") {
console.error("NUNCA rode seed em produção!");
process.exit(1);
}
console.log("Criando 100 clientes...");
for (let i = 0; i < 100; i++) {
const cliente = await db.cliente.create({
data: { ...criarCliente(), isTest: true },
});
// 1-5 pedidos por cliente
const numPedidos = Math.floor(Math.random() * 5) + 1;
for (let j = 0; j < numPedidos; j++) {
await db.pedido.create({
data: { ...criarPedido(cliente.id), isTest: true },
});
}
}
console.log("Seed completo!");
}
seed();Atenção
isTest: true é crítica. Em produção, filtros por isTest: false evitam que teste misture com dados reais. Também facilita limpeza periódica de ambiente staging: DELETE WHERE is_test = true AND created_at < NOW() - INTERVAL ‘30 days’.Para staging persistente
- Marque todos os registros com
is_test = true. - Limpe periodicamente (30-60 dias) para não acumular lixo.
- Regenere antes de demos importantes para cenários frescos.
- Documente o processo de seed no README.
Cenários específicos
Usuário com padrões de compra realistas
// Cliente fiel (muitos pedidos, valor médio)
export function criarClienteFiel() {
const cliente = criarCliente();
const pedidos = Array.from({ length: faker.number.int({ min: 20, max: 50 }) },
() => ({
...criarPedido(cliente.id),
valor: faker.number.float({ min: 100, max: 500 }),
}),
);
return { cliente, pedidos };
}
// Cliente novo (poucos pedidos, valor baixo)
export function criarClienteNovo() {
const cliente = { ...criarCliente(), criadoEm: faker.date.recent({ days: 30 }) };
const pedidos = Array.from({ length: faker.number.int({ min: 1, max: 3 }) },
() => ({
...criarPedido(cliente.id),
valor: faker.number.float({ min: 50, max: 150 }),
}),
);
return { cliente, pedidos };
}
// Cliente VIP (poucos pedidos, valor altíssimo)
export function criarClienteVip() {
const cliente = criarCliente();
const pedidos = Array.from({ length: faker.number.int({ min: 3, max: 10 }) },
() => ({
...criarPedido(cliente.id),
valor: faker.number.float({ min: 5000, max: 50000 }),
}),
);
return { cliente, pedidos };
}Distribuição realista com weights
// Gera mix realista de clientes: 70% novos, 25% fiéis, 5% VIP
export function gerarBaseClientes(total: number) {
const clientes = [];
for (let i = 0; i < total; i++) {
const tipo = faker.helpers.weightedArrayElement([
{ value: "novo", weight: 70 },
{ value: "fiel", weight: 25 },
{ value: "vip", weight: 5 },
]);
switch (tipo) {
case "novo":
clientes.push(criarClienteNovo());
break;
case "fiel":
clientes.push(criarClienteFiel());
break;
case "vip":
clientes.push(criarClienteVip());
break;
}
}
return clientes;
}Documentos brasileiros específicos
Para CPFs, CNPJs, CEPs e dados locais, faker-js/locale/pt_BR cobre a maioria:
| Critério | Exemplo de saída |
|---|---|
| faker.br.cpf() | 14339725095 |
| faker.br.cnpj() | 62030781000162 |
| faker.person.fullName() | João da Silva |
| faker.phone.number() | (11) 98765-4321 |
| faker.location.city() | São Paulo |
| faker.location.state() | São Paulo (ou SP) |
| faker.location.zipCode() | 01001-000 |
| faker.company.name() | Empresa XYZ LTDA |
Anonimização de dados de produção
Em alguns cenários (performance testing com distribuição real), você precisa de dados que refletem produção. Anonimize antes de copiar para staging:
// Script de anonimização
import { faker } from "@faker-js/faker/locale/pt_BR";
import crypto from "crypto";
function anonimizar(registro: Record<string, unknown>) {
return {
...registro,
// Mantenha ID (preserva relacionamentos)
// id: registro.id,
// Substitua PII
nome: faker.person.fullName(),
email: faker.internet.email(),
cpf: faker.br.cpf(),
telefone: faker.phone.number(),
// Hash de campos sensíveis que precisam ser únicos
senha: crypto.randomBytes(32).toString("hex"),
// Mantenha valores numéricos e datas para análise
// valor, created_at, etc.
};
}
// Rode uma vez ao migrar de prod para staging
const dadosProducao = await buscarDadosDeProducao();
const anonimizados = dadosProducao.map(anonimizar);
await salvarEmStaging(anonimizados);Vai mais fundo
Teste de carga com volume realista
Para testar performance com milhões de linhas, gere em batch e persista:
import { faker } from "@faker-js/faker/locale/pt_BR";
import { createWriteStream } from "node:fs";
import { stringify } from "csv-stringify";
const TOTAL = 1_000_000;
const BATCH = 10_000;
const stream = createWriteStream("./dados-teste.csv");
const csv = stringify({ header: true, columns: ["id", "nome", "cpf", "email"] });
csv.pipe(stream);
for (let i = 0; i < TOTAL; i += BATCH) {
const batch = Array.from({ length: BATCH }, () => ({
id: faker.string.uuid(),
nome: faker.person.fullName(),
cpf: faker.br.cpf(),
email: faker.internet.email(),
}));
for (const row of batch) csv.write(row);
console.log(`Progresso: ${i + BATCH} / ${TOTAL}`);
}
csv.end();
console.log("CSV com 1M registros gerado.");Erros clássicos
- Usar dados reais “só esta vez”: vira prática.
- Seed na maioria dos testes, sem em alguns: inconsistência confusa.
- Factories sem helpers de variação: sempre cria o mesmo cenário, não exercita edge cases.
- Não marcar registros como teste: risco de misturar com produção.
- Gerar cartão de crédito que passa Luhn mas é de testador real: violação se a pessoa reclamar.
- Dados em inglês em sistema PT-BR: use locale correto.
- Gerar em produção por engano: sempre verifique NODE_ENV antes.
- Ignorar distribuição realista: todos os clientes com 10 pedidos não é cenário real.
Checklist de uso saudável
- Biblioteca de faker correta para a linguagem instalada?
- Locale correto configurado (pt_BR para apps brasileiros)?
- Seed determinístico em CI?
- Flag
isTest: trueem todos os registros de teste? - Seed script verifica ambiente antes de rodar?
- Factories para entidades relacionadas?
- Cenários com distribuição realista (não uniforme)?
- Limpeza periódica de staging?
- Documentação do processo de seed no README?
Dados fictícios em uma frase
Dados fictícios transformam testes de frágeis e ilegais em robustos e conformes com LGPD. Bibliotecas como Faker-js e Faker (Python) resolvem 95% dos casos em poucas linhas. Combinado com factories e seed determinístico, você tem arsenal completo para qualquer cenário — de unit test minúsculo a load test com milhões de registros.
Perguntas frequentes
Por que não usar dados reais em testes?+
Quatro razões. (1) LGPD: usar dado real em testes sem base legal viola a lei. (2) Vazamento: staging tem menos segurança que prod; dados reais ali viram risco de incidente. (3) Reprodutibilidade: cenários de teste precisam de dados controlados. (4) Volume: você não tem dados reais suficientes para teste de carga. Dado fictício resolve os 4 com zero risco jurídico.
Qual a diferença entre mock, fake e stub?+
Fake/dado fictício: objeto com dados realistas usado como entrada (Faker gera). Stub: retorno predeterminado de função mockada (ex: API responde sempre 200). Mock: objeto que verifica interações esperadas (métodos foram chamados, com quais argumentos). Os três se complementam em testes. Este artigo foca em fakes/dados fictícios — a base de qualquer bom teste.
Qual biblioteca de fake data é padrão em JavaScript?+
@faker-js/faker é o padrão absoluto em 2026. ~350k downloads/semana, mantido ativamente, suporta múltiplos idiomas (incluindo pt_BR), geração de nomes, CPFs, endereços, UUIDs, datas, e mais. Alternativas: chance.js (mais focado em valores aleatórios), casual (leve). Para dados brasileiros específicos: brazilian-values, @fake-br/faker. Para 90% dos casos, faker-js basta.
Seed determinístico é obrigatório em CI?+
Fortemente recomendado. Sem seed, cada execução gera dados diferentes — um teste que falha em CI pode ser impossível de reproduzir localmente. Com seed fixo (faker.seed(42)), mesma execução → mesmos dados → bug consistente. Em pipeline de CI: use seed baseado em número do build (PR #42 → seed 42), garantindo variação entre PRs mas reprodutibilidade dentro do mesmo PR.
Quando dados fictícios NÃO bastam?+
Testes que dependem de padrões específicos de produção: (1) performance em queries que sofrem com distribuição de dados (scan vs index); (2) edge cases descobertos em prod que não aparecem em dados aleatórios; (3) bugs que envolvem escala (milhões de linhas com padrões reais). Solução: use produção anonimizada — mascare CPF, nome, e-mail, mantendo distribuição estatística e relacionamentos.
Como gerar dados fictícios coerentes entre entidades?+
Use factories com relações. Ex: Pedido tem cliente_id; gere cliente primeiro, use id no pedido. Frameworks como factory_bot (Ruby) e FactoryBot (JS) resolvem. Em Faker puro, crie função factory_cliente() que retorna um cliente completo, depois factory_pedido(clientId) que usa o ID retornado. Dados relacionais coerentes facilitam debug — quando falha, o cenário faz sentido.
Faker gera dados que passam em validação (CPF, CNPJ, cartão)?+
Depende. Faker.br.cpf() gera CPF que passa no módulo 11 (válido matematicamente). Cartão de crédito: faker.finance.creditCardNumber() gera número válido pelo algoritmo de Luhn mas não é cartão real. Telefone, CEP, cor, UUID: todos válidos em formato. Para cenários específicos, verifique a doc. Em dúvida, rode validador sobre o gerado — se falha, implemente gerador custom.
Quanto tempo leva para gerar 1 milhão de registros fictícios?+
Em Node.js com Faker: ~30-60 segundos (dependendo da complexidade do objeto). Em Python com Faker: ~2-3 minutos. Para volumes maiores ou performance crítica, gere em batch e persista em CSV para reuso. Mimesis (Python) é 3-5x mais rápido que Faker. Para hiper-escala, considere gerar em SQL direto com random() nativo do Postgres.
Artigos relacionados
Como Validar CPF e CNPJ (2026): Algoritmo, Código em JavaScript e Boas Práticas
Guia completo de validação de CPF e CNPJ: algoritmo do módulo 11 passo a passo, implementação em JavaScript, máscara em formulários, erros clássicos e LGPD.
Como Gerar CNPJ Válido em JavaScript (2026): Algoritmo Passo a Passo
Implementação completa do algoritmo gerador de CNPJ em JavaScript: módulo 11, pesos corretos, função pronta em TypeScript, batch em lote, uso em testes e LGPD.
Como Gerar CPF Válido em JavaScript: Algoritmo Passo a Passo (2026)
Implementação completa do algoritmo gerador de CPF em JavaScript: módulo 11 dos dígitos verificadores, geração por estado, batch, função TypeScript pronta, comparação com bibliotecas e LGPD em testes.
CPF para Testes em Desenvolvimento (2026): Como Usar, LGPD e Boas Práticas
Guia completo de CPF em ambiente de testes: por que nunca usar real, como gerar em massa, conformidade com LGPD, ferramentas por linguagem e estratégias para equipes.