Massa de Dados pra QA Brasileira: Guia Prático de Automação
Massa de Dados pra QA Brasileira: Guia Prático de Automação
TL;DR: Dados sintéticos gerados via API (não copiar produção) respeitam LGPD, economizam horas de setup e garantem testes que funcionam. Use FakeForge pra dados brasileiros validados, integre em Selenium/Cypress/Playwright/BDD, rode em CI/CD.
1. O que é Test Data Management (TDM)
Test Data Management é a prática de gerar, manter e distribuir dados para testes de software. Não é copiar produção (risco legal + LGPD), nem rodar testes sem dados (cobertura fake).
TDM bem feito significa: dados que passam em validação real do sistema, reproduzíveis entre runs de teste, conformes com leis de proteção de dados, e fáceis de integrar em pipelines automatizados.
Três problemas que TDM ruim causa
Testes lentos: Você cria dados manualmente no banco antes de rodar suite. 5 minutos de setup pra cada run. Em CI/CD, rodas testes 50 vezes por dia? São 250 minutos desperdiçados.
Testes flaky: Dados inválidos (CPF com checksum errado, CEP que não existe, estado desatualizado). Teste passa hoje, quebra amanhã. Você fica debugando se é culpa da sua aplicação ou do dado.
Risco legal: Cópia de dados reais de clientes em staging é viola LGPD. Multa vai de R$50 mil a R$50 milhões. Uma auditoria descobre, e você explica pra diretor por que copiou CPF de clientes reais pra teste.
2. Massa de dados sintética vs cópia de produção
A confusão acontece aqui: "precisamos de dados reais de clientes pra testar o sistema como ele realmente será". Essa lógica é perigosa.
Dados sintéticos (recomendado)
- Gerados algoritmicamente, não extraídos de clientes reais
- Passam em validação real (CPF mod-11, CNPJ checksum, CEP geográfico)
- LGPD-compliant: nenhum dado pessoal real é copiado
- Reproduzíveis: mesma seed gera mesmos dados
- Rápidos de gerar: 1 chamada de API por test run
Cópia de produção (evitar sempre)
- Expõe dados pessoais reais em staging (CPF, email, endereço de clientes)
- LGPD multa R$50 mil a R$50 milhões se auditoria descobre
- Não é reproduzível: dados mudam em produção, seu teste fica incoerente
- Risco de: erro SQL que deleta cliente real, ou teste corrompe produção
3. Arquitetura TDM pra time QA brasileiro
Existem padrões de design que time QA usa pra organizar geração de dados. Aqui estão os principais:
Pattern 1: Factory Pattern
Você cria uma classe que centraliza geração de dados:
class PessoaFactory {
static async gerar(sobrescritas = {}) {
const response = await fetch(
'https://fakeforge.com.br/api/generate?type=pessoa&quantity=1'
);
const pessoa = (await response.json()).data[0];
return { ...pessoa, ...sobrescritas };
}
}
// No seu teste:
test('Cadastro com dados factory', async () => {
const pessoa = await PessoaFactory.gerar({
email: 'custom@example.com'
});
await cadastrar(pessoa);
expect(resultado).toBe('sucesso');
});Pattern 2: Builder Pattern
Mais flexível, permite chain de métodos:
class PessoaBuilder {
constructor() {
this.data = {};
}
async comCPF(cpf = null) {
if (!cpf) {
const resp = await fetch(
'https://fakeforge.com.br/api/generate?type=cpf&quantity=1'
);
cpf = (await resp.json()).data[0].cpf;
}
this.data.cpf = cpf;
return this;
}
comEmail(email) {
this.data.email = email;
return this;
}
async build() {
return this.data;
}
}
// No seu teste:
test('Cadastro com builder', async () => {
const pessoa = await new PessoaBuilder()
.comEmail('custom@example.com')
.build();
await cadastrar(pessoa);
});Pattern 3: API-first (recomendado)
Você chama a API antes de rodar suite inteira. Fixture gerada uma vez, reutilizada em todos os testes:
// setup.js - roda antes de todos os testes
import fs from 'fs/promises';
export async function setupTestData() {
const response = await fetch(
'https://fakeforge.com.br/api/generate?type=pessoa&quantity=50&format=json'
);
const dados = (await response.json()).data;
await fs.writeFile(
'./fixtures/pessoas.json',
JSON.stringify(dados, null, 2)
);
return dados;
}
// Em cada teste:
import { readFileSync } from 'fs';
const pessoas = JSON.parse(
readFileSync('./fixtures/pessoas.json', 'utf8')
);
test('Cadastro', () => {
cadastrar(pessoas[0]);
})
test('Atualização', () => {
atualizar(pessoas[1]);
});4. Ferramentas e integrações
FakeForge + Selenium
Selenium é browser automation. FakeForge gera dados. Integração simples:
from selenium import webdriver
import requests
# Gerar dados
res = requests.get(
'https://fakeforge.com.br/api/generate?type=pessoa&quantity=1'
)
pessoa = res.json()['data'][0]
# Usar no browser
driver = webdriver.Chrome()
driver.get('https://app/cadastro')
driver.find_element('id', 'cpf').send_keys(pessoa['cpf'])
driver.find_element('id', 'email').send_keys(pessoa['email'])
driver.find_element('id', 'submit').click()
# Validar
assert driver.find_element('class', 'sucesso').text == 'Cadastro realizado'FakeForge + Cypress
Cypress é mais moderno, built-in request, melhor pra dados br:
describe('Cadastro E2E', () => {
it('Cadastro com CPF válido', () => {
cy.request({
method: 'GET',
url: 'https://fakeforge.com.br/api/generate',
qs: {
type: 'pessoa',
quantity: 1,
format: 'json'
}
}).then((response) => {
const pessoa = response.body.data[0];
cy.visit('/cadastro');
cy.get('input[name="cpf"]').type(pessoa.cpf);
cy.get('input[name="email"]').type(pessoa.email);
cy.get('input[name="nome"]').type(pessoa.nome);
cy.get('button[type="submit"]').click();
cy.get('.sucesso').should('be.visible');
});
});
});FakeForge + Playwright
Playwright é cross-browser, mais rápido que Cypress:
import { test, expect } from '@playwright/test';
test('E2E Ecommerce com dados completos', async ({ page, request }) => {
// Gerar dados da FakeForge
const response = await request.get(
'https://fakeforge.com.br/api/generate?type=compra&quantity=1'
);
const compra = (await response.json()).data[0];
// Navegar e preencher
await page.goto('/checkout');
await page.fill('input[name="cpf"]', compra.cpf);
await page.fill('input[name="endereco"]', compra.endereco);
await page.fill('input[name="cartao"]', compra.cartao);
// Confirmar
await page.click('button:has-text("Confirmar")');
await page.waitForURL('/confirmacao');
// Validar
const sucesso = await page.isVisible('.pedido-confirmado');
expect(sucesso).toBeTruthy();
});FakeForge + Cucumber/Gherkin (BDD)
BDD integra linguagem natural com teste. FakeForge em step definitions:
# features/cadastro.feature
Feature: Cadastro de usuários
Scenario: Cadastro com CPF válido
Given tenho um CPF válido gerado
When submeto o formulário de cadastro
Then vejo mensagem de sucesso
// stepDefinitions.js
import { Given, When, Then } from '@cucumber/cucumber';
import fetch from 'node-fetch';
let usuario = {};
Given('tenho um CPF válido gerado', async () => {
const res = await fetch(
'https://fakeforge.com.br/api/generate?type=pessoa&quantity=1'
);
usuario = (await res.json()).data[0];
});
When('submeto o formulário de cadastro', async () => {
await page.fill('#cpf', usuario.cpf);
await page.fill('#email', usuario.email);
await page.click('button[type="submit"]');
});
Then('vejo mensagem de sucesso', async () => {
const msg = await page.textContent('.sucesso');
expect(msg).toContain('Cadastro realizado');
});5. Exemplos de código completos
Exemplo 1: Teste cadastro com Python + Selenium
#!/usr/bin/env python3
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def test_cadastro_cpf_valido():
# 1. Gerar CPF válido via FakeForge
response = requests.get(
'https://fakeforge.com.br/api/generate',
params={'type': 'cpf', 'quantity': 1, 'format': 'json'}
)
cpf = response.json()['data'][0]['cpf']
# 2. Abrir browser e acessar cadastro
driver = webdriver.Chrome()
driver.get('https://staging.app/cadastro')
# 3. Preencher formulário
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, 'cpf'))
)
driver.find_element(By.ID, 'cpf').send_keys(cpf)
driver.find_element(By.ID, 'nome').send_keys('João Silva')
driver.find_element(By.ID, 'email').send_keys('joao@example.com')
# 4. Submeter
driver.find_element(By.XPATH, '//button[@type="submit"]').click()
# 5. Validar sucesso
sucesso = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, 'sucesso'))
)
assert 'Cadastro realizado' in sucesso.text
driver.quit()
print(f'✓ Teste passou com CPF: {cpf}')
if __name__ == '__main__':
test_cadastro_cpf_valido()Exemplo 2: E2E Ecommerce com TypeScript + Playwright
import { test, expect } from '@playwright/test';
interface Compra {
cpf: string;
cnpj: string;
nome: string;
endereco: string;
cep: string;
telefone: string;
email: string;
}
async function gerarDados(): Promise<Compra> {
const response = await fetch(
'https://fakeforge.com.br/api/generate?type=compra&quantity=1&format=json'
);
const { data } = await response.json();
return data[0];
}
test('Compra E2E com dados BR validados', async ({ page, request }) => {
const compra = await gerarDados();
// Acessar site
await page.goto('/');
// Adicionar produto
await page.click('button:has-text("Adicionar ao carrinho")');
// Ir pra checkout
await page.click('a[href="/checkout"]');
// Preencher dados pessoais
await page.fill('#cpf', compra.cpf);
await page.fill('#email', compra.email);
await page.fill('#telefone', compra.telefone);
// Preencher endereço (CEP já correlaciona estado-cidade)
await page.fill('#cep', compra.cep);
await page.fill('#endereco', compra.endereco);
// Confirmar
await page.click('button:has-text("Confirmar compra")');
// Esperar redirecionamento
await page.waitForURL('**/pedido-confirmado');
// Validar
const pedidoNum = await page.textContent('#pedido-numero');
expect(pedidoNum).toMatch(/^PED-d{10}$/);
console.log(`✓ Pedido ${pedidoNum} criado com CPF ${compra.cpf}`);
});Exemplo 3: BDD + Cypress com fixture
// cypress/fixtures/dados.json
// Pré-gerado via: curl https://fakeforge.com.br/api/generate?type=pessoa&quantity=50&format=json > dados.json
describe('BDD - Cadastro com dados fixture', () => {
before(() => {
cy.fixture('dados.json').then((dados) => {
Cypress.env('pessoas', dados.data);
});
});
it('Cadastro primeira pessoa', () => {
const pessoa = Cypress.env('pessoas')[0];
cy.visit('/cadastro');
cy.get('#cpf').type(pessoa.cpf);
cy.get('#email').type(pessoa.email);
cy.get('#nome').type(pessoa.nome);
cy.get('button[type="submit"]').click();
cy.get('.sucesso').should('contain', 'Cadastro realizado');
});
it('Cadastro segunda pessoa', () => {
const pessoa = Cypress.env('pessoas')[1];
cy.visit('/cadastro');
cy.get('#cpf').type(pessoa.cpf);
cy.get('#email').type(pessoa.email);
cy.get('#nome').type(pessoa.nome);
cy.get('button[type="submit"]').click();
cy.get('.sucesso').should('contain', 'Cadastro realizado');
});
});6. Edge cases importantes do Brasil
Edge Case 1: CPF inválido pra testar front-end
Quando você quer testar se o front-end rejeita CPF inválido, FakeForge pode gerar CPFs propositalmente inválidos:
// Teste que front-end rejeita CPF
test('Front rejeita CPF inválido', async () => {
const cpfInvalido = '111.111.111-11'; // Repetido, sempre inválido
cy.visit('/cadastro');
cy.get('#cpf').type(cpfInvalido);
cy.get('button[type="submit"]').click();
cy.get('.erro').should('contain', 'CPF inválido');
});Edge Case 2: CNPJ alfanumérico 2026
A partir de julho de 2026, CNPJs podem ter letras nas primeiras 8 posições. Teste isso:
test('Sistema aceita CNPJ alfanumérico', async () => {
// Gerar CNPJ no novo formato
const response = await fetch(
'https://fakeforge.com.br/api/generate?type=cnpj&format=alfanumerico&quantity=1'
);
const cnpj = (await response.json()).data[0].cnpj; // Ex: AB123456000177
cy.visit('/cadastro-empresa');
cy.get('#cnpj').type(cnpj);
cy.get('button[type="submit"]').click();
cy.get('.sucesso').should('be.visible');
});Edge Case 3: CEP inexistente
Alguns CEPs foram desativados por fusão de cidades. Teste:
test('Validador rejeita CEP desativado', async () => {
const cepDesativado = '12345-678'; // Fictício
cy.visit('/cadastro');
cy.get('#cep').type(cepDesativado);
cy.get('#cep').blur(); // Trigger validação
cy.get('.erro-cep').should('contain', 'CEP não encontrado');
});Edge Case 4: Telefone com 9 (celular moderno)
Celular tem 9 entre DDD e número: 11 9 8765-4321 (não é 11 8765-4321).
test('Validador aceita telefone moderno com 9', async () => {
const telefone = '+5511987654321'; // 11 DDD + 9 + 8 dígitos
cy.visit('/cadastro');
cy.get('#telefone').type(telefone);
cy.get('button[type="submit"]').click();
cy.get('.sucesso').should('be.visible');
});7. CI/CD integration
Integrar FakeForge em pipeline CI/CD significa: chamar API pra gerar dados antes de rodar testes, salvar em arquivo, passar path pro seu test runner.
GitHub Actions
name: QA Testes Automatizados
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Instalar dependências
run: npm install
- name: Gerar massa de dados via FakeForge
run: |
curl -s 'https://fakeforge.com.br/api/generate' \
--get --data-urlencode 'type=pessoa' \
--data-urlencode 'quantity=100' \
--data-urlencode 'format=json' \
> fixtures/pessoas.json
- name: Rodar testes Selenium
run: npm run test:selenium
- name: Rodar testes Cypress
run: npm run test:e2e
- name: Upload relatório
if: always()
uses: actions/upload-artifact@v2
with:
name: test-reports
path: reports/GitLab CI
stages:
- test
QA_Tests:
stage: test
image: node:18
script:
- npm install
- |
curl -s 'https://fakeforge.com.br/api/generate?type=pessoa&quantity=100&format=json' \
> fixtures/pessoas.json
- npm run test:cypress
- npm run test:selenium
artifacts:
paths:
- reports/
expire_in: 1 week8. Conformidade LGPD pro time QA
LGPD (Lei Geral de Proteção de Dados) regula como dados pessoais são coletados e usados no Brasil. Para QA, os riscos principais são:
1. Não copiar dados de produção pra staging
Quando você copia tabela de clientes reais (nome, CPF, email) pra staging, você está exposição dados pessoais. Auditoria LGPD descobre e multa R$50 mil mínimo.
2. Dados sintéticos vs anonimização
Existe diferença:
- Sintéticos: Nunca foram dados reais. Gerados algoritmicamente. LGPD-seguro por design.
- Anonimizados: Foram dados reais, depois tiveram identificadores removidos. Mais difícil garantir que não são re-identificáveis.
3. Documentar pra DPO
Se sua empresa tem Data Protection Officer (DPO), documente: "Time QA usa FakeForge pra gerar dados sintéticos que passam em validação real. Nenhum dado pessoal real é copiado pra staging. Dados são descartáveis após teste."
Com essa documentação, você está LGPD-compliant. FakeForge já oferece documentação de LGPD pronta pra você passar pro DPO.
FAQ
Qual a diferença entre FakeForge e Faker.js em produção?+
Faker.js é biblioteca JavaScript pra gerar dados no seu código. FakeForge é API centralizada. Se você roda testes em múltiplas linguagens (Python, Java, Node), FakeForge é mais eficiente. E FakeForge valida CPF/CNPJ realmente, Faker não.
Posso usar FakeForge pra testes de carga?+
Sim. Limite é 10 mil registros por chamada. Pra teste de carga com 100 mil registros, rode 10 chamadas antes de iniciar o teste. Tudo leva menos de 2 segundos.
FakeForge é determinístico? Posso ter os mesmos dados em runs diferentes?+
Sim. Passe um parametro seed=123 e você sempre vai gerar os mesmos dados. Útil pra reproduzir bugs.
Como saber se FakeForge é melhor que Mockaroo pra meu time?+
Se seu app valida CPF/CNPJ com mod-11, precisa de CEP por estado, ou trabalha com pagamento (PIX), FakeForge é escolha obvia. Se é app puramente internacional, Mockaroo é melhor.
FakeForge vai adicionar suporte a mais documentos brasileiros?+
Sim. RG, CNH, PIS/PASEP estão na roadmap. Já estão suportados CPF, CNPJ, PIX, CEP, telefone, empresa.
Quanto custa FakeForge pra meu time QA?+
Gratuito até 50 chamadas por dia. R$29/mês pro plano Dev (10 mil chamadas/dia). Pra time QA com 50-100 runs de teste por dia, plano gratuito já cobre.
Conclusão
Massa de dados é a base de QA. Se você gera dados manualmente, copia de produção (LGPD risk), ou confia em Faker sem validação, você está deixando bugs passar.
FakeForge resolve isso: dados válidos, gerados em tempo real, integrados em Selenium/Cypress/Playwright/BDD, LGPD-compliant, pronto pra CI/CD. Uma API, nenhuma configuração, grátis até 50 chamadas por dia.
Próximo passo: gere seu primeiro CPF agora, depois integre em seu primeiro teste. Tempo total: 10 minutos.
Recursos úteis
Everton, fundador do FakeForge