← Voltar ao blog

Massa de Dados pra QA Brasileira: Guia Prático de Automação

·15 min de leitura

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 week

8. 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.

Everton, fundador do FakeForge

Achou útil? Compartilha: