LGPD em testes de software: guia prático para devs
LGPD em testes de software: guia prático para devs
Usar dados reais de clientes em ambiente de teste é mais que descuido de segurança, é uma violação direta da Lei Geral de Proteção de Dados (Lei 13.709/2018). Este guia mostra como estruturar fixtures, seeds e pipelines de CI/CD sem tocar em dados pessoais reais, mantendo conformidade com a LGPD e reprodutibilidade nos testes.
---
Usar dados reais em testes viola a LGPD
O que a lei diz sobre finalidade e necessidade (Art. 6º, I e III)
A LGPD estabelece princípios que se aplicam a qualquer tratamento de dado pessoal, inclusive dentro da sua empresa. O Art. 6º, I define o princípio da finalidade: o tratamento só pode ocorrer para propósitos legítimos, específicos e informados ao titular. O Art. 6º, III define o princípio da necessidade: o tratamento deve se limitar ao mínimo indispensável para atingir sua finalidade.
Quando um titular de dados cedeu o CPF para contratar um serviço, a finalidade declarada não incluiu "ser usado como fixture em testes unitários". O uso nesse contexto viola o Art. 6º, I, independente de qualquer controle de acesso interno.
Por que "ambiente interno" não é base legal suficiente
Equipes argumentam que banco de testes é "ambiente controlado, sem saída para fora". A lei não faz essa distinção. O Art. 5º, X define tratamento como "toda operação realizada com dados pessoais", incluindo "armazenamento, utilização, acesso". Um banco de staging com dump de produção é tratamento de dados pessoais, ponto.
Além disso, "ambiente interno" expande o círculo de acesso. Estagiários, freelancers contratados, pipelines de CI com secrets vazados, snapshots de banco em logs de debug, todos esses vetores multiplicam o risco sem qualquer base legal que os cubra.
Incidentes reais: o caso dos dumps de produção compartilhados por e-mail
Um padrão recorrente em times de produto: o dev precisa de dados para reproduzir um bug de produção, pede ao DBA um "dump pequeno" e recebe um CSV com 50 mil linhas por e-mail. O arquivo fica na caixa de entrada, no laptop, eventualmente no repositório como fixtures/users_sample.csv.
A ANPD já publicou Resolução CD/ANPD nº 2/2022 sobre comunicação de incidentes. Dump de produção exposto em repositório Git se enquadra como incidente de segurança com notificação obrigatória em até 72 horas quando o acesso não autorizado é confirmado.
---
As bases legais que importam para dados de teste (LGPD Art. 7º)
Consentimento (Art. 7º, I) é inviável para fixtures
Consentimento exige que o titular autorize de forma livre, informada e inequívoca o tratamento para finalidade específica. Nenhuma empresa vai contatar cada titular cujo CPF aparece em um fixture de teste para pedir autorização. Operacionalmente inviável. Base legal descartada.
Legítimo interesse (Art. 7º, IX) e seus limites
Legítimo interesse permite tratar dados quando o controlador tem interesse legítimo, desde que não prevaleçam os direitos fundamentais do titular. Para dados de teste, a justificativa seria "garantir qualidade do software". O problema: a ANPD exige que o controlador demonstre que o tratamento é necessário e proporcional. Dados sintéticos atingem o mesmo objetivo sem tratar dados reais. Logo, o interesse legítimo não sobrevive ao teste de proporcionalidade do Art. 7º, IX.
Anonimização como saída: quando o dado sai do escopo da lei (Art. 5º, III)
A melhor saída legal não é uma base legal: é remover o dado do escopo da lei. O Art. 5º, III define dado anonimizado como "dado relativo a titular que não possa ser identificado, considerando a utilização de meios técnicos razoáveis e disponíveis na ocasião do tratamento". Dado anonimizado de forma irreversível não é dado pessoal. Não existe tratamento a justificar.
---
Diferença entre anonimização e pseudonimização na prática
Pseudonimização (Art. 13, §4º): ainda é dado pessoal
Pseudonimização substitui o identificador direto por um pseudônimo. Trocar o CPF 123.456.789-09 por um hash SHA-256 é pseudonimização. Se a tabela de correspondência existe em algum lugar, o dado é reversível e continua sendo dado pessoal sob a LGPD Art. 13, §4º.
Anonimização irreversível: critérios do ANPD
A ANPD publicou o Guia Orientativo de Anonimização com três critérios principais: não-individualização, não-vinculação e não-inferência. Um CPF gerado sinteticamente que nunca existiu não falha nenhum dos três critérios. É, por definição, anônimo desde a origem.
Qual técnica usar em cada camada (banco, log, API mock)
| Camada | Técnica recomendada | Técnica a evitar |
|---|---|---|
| Banco de dados de teste | Geração sintética desde o seed | Dump mascarado com hash reversível |
| Logs de aplicação | Substituição por placeholder estático | Truncagem parcial (ex: 123.XXX.XXX-09) |
| API mock / WireMock | Fixture com dados gerados | Captura de tráfego de produção |
| Snapshots de banco (CI) | Gerados em build time | Cópia automatizada de staging |
---
Estratégias para construir fixtures sem dados reais
Geração sintética: dados correlacionados
O maior problema de dados aleatórios mal gerados não é a LGPD, é que quebram as próprias validações do sistema. Um CPF com dígitos verificadores errados vai falhar na camada de negócio antes de chegar ao banco. Dados sintéticos úteis precisam ser internamente consistentes: CPF válido, endereço no mesmo estado que o CEP, DDD de celular compatível com a cidade.
// Geração de fixture completa via FakeForge API
async function gerarPessoa() {
const res = await fetch(
"https://fakeforge.com.br/api/generate?type=pessoa&quantity=1&format=json"
);
const { data } = await res.json();
return data[0] as {
nome: string;
cpf: string;
email: string;
telefone: string;
endereco: {
logradouro: string;
bairro: string;
cidade: string;
estado: string;
cep: string;
};
};
}A API retorna nome, CPF com dígito verificador correto e endereço correlacionado ao mesmo estado. Detalhes em /docs.
Mascaramento de produção: regras por campo e riscos residuais
Quando o time insiste em partir de dados reais, mascaramento é o caminho. A regra básica: substituir o campo inteiro por dado sintético válido, nunca truncar ou embaralhar parcialmente.
// Substituir CPF real por CPF sintético em dump (TypeScript)
import { execSync } from "child_process";
function mascaraCpf(linha: string): string {
// CPF no formato 000.000.000-00
return linha.replace(
/\b\d{3}\.\d{3}\.\d{3}-\d{2}\b/g,
() => gerarCpfSintetico()
);
}
function gerarCpfSintetico(): string {
// Gera 9 dígitos base
const base = Array.from({ length: 9 }, () => Math.floor(Math.random() * 10));
const d1 = calcDigito(base, 10);
const d2 = calcDigito([...base, d1], 11);
const digits = [...base, d1, d2];
return `${digits.slice(0, 3).join("")}.${digits.slice(3, 6).join("")}.${digits.slice(6, 9).join("")}-${digits.slice(9).join("")}`;
}
function calcDigito(nums: number[], peso: number): number {
const soma = nums.reduce((acc, n, i) => acc + n * (peso - i), 0);
const resto = soma % 11;
return resto < 2 ? 0 : 11 - resto;
}AVISO: mascaramento de dump tem risco residual de reidentificação por combinação de campos (nome + CEP + data de nascimento). Prefira geração sintética pura sempre que o caso de uso permitir.
Seed determinístico: reprodutibilidade sem dados reais
// Seed factory para Jest/Vitest
import { beforeAll } from "vitest";
let fixtures: Awaited<ReturnType<typeof gerarPessoa>>[] = [];
beforeAll(async () => {
const res = await fetch(
"https://fakeforge.com.br/api/generate?type=pessoa&quantity=20&format=json"
);
const { data } = await res.json();
fixtures = data;
});
export function getFixture(index: number) {
return fixtures[index % fixtures.length];
}Para reprodutibilidade total em CI, persista o JSON gerado como artefato de build e reutilize-o em reruns. Ver seção de pipeline abaixo.
---
CPF, CNPJ e documentos brasileiros em testes
Algoritmo mod-11 e por que CPFs aleatórios quebram validações
O CPF usa dois dígitos verificadores calculados por módulo 11. Um CPF com 11 dígitos aleatórios tem aproximadamente 1% de chance de passar na validação. Em uma suíte com 500 registros, isso gera 495 falhas silenciosas no campo de documento antes de qualquer lógica de negócio ser testada. Use /gerador-cpf para CPF válido para fixtures ou implemente o algoritmo mod-11 localmente como no exemplo acima.
CNPJ Alfanumérico (vigência 01/07/2026): impacto em suítes de teste existentes
A Receita Federal publicou a IN RFB 2.229/2024 que autoriza CNPJ com letras nas 8 primeiras posições a partir de 01/07/2026. Regex que aceita apenas \d{14} vai rejeitar CNPJs novos. Atualize fixtures e validadores antes da data de vigência. O gerador de CNPJ Alfanumérico já gera no novo formato para você testar a migração.
Outros documentos: RG, CNH, PIS/PASEP, Título de Eleitor
Cada documento tem regra de formação própria. O gerador de CNH aplica o algoritmo DENATRAN. O gerador de PIS/PASEP usa mod-11 com pesos específicos. O Título de Eleitor inclui código de zona e seção. Números aleatórios nesses campos falham em sistemas que fazem qualquer validação de formato.
---
Dados financeiros sintéticos em ambiente de teste
Chaves PIX válidas sem CPF/CNPJ real
A chave PIX do tipo CPF ou CNPJ precisa de documento válido para ser aceita em validações. Use /gerador-pix para gerar chaves dos quatro tipos (CPF, CNPJ, e-mail, celular, aleatória) com formato correto para não travar fluxos de pagamento em testes de integração.
Cartões com Luhn correto (Visa, Mastercard, Elo, Hipercard)
O algoritmo de Luhn valida se um número de cartão é estruturalmente possível. Um número aleatório de 16 dígitos falha em qualquer biblioteca de validação de cartão. O gerador de cartão cobre Visa, Mastercard, Elo e Hipercard com BIN correto e Luhn válido.
Contas bancárias: códigos COMPE reais, números fictícios
Conta bancária precisa de código COMPE real (341 para Itaú, 260 para Nubank, 077 para Inter). Números de agência e conta são fictícios, mas o par banco+formato-de-conta deve ser válido para não rejeitar na camada de validação de formulário. O gerador de conta bancária usa os 17 códigos COMPE do catálogo do BACEN.
---
Pipeline de CI/CD conforme com a LGPD
Separar variáveis de ambiente: produção vs. staging vs. teste
# .github/workflows/test.yml
jobs:
test:
runs-on: ubuntu-latest
env:
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
# Nunca: DATABASE_URL: ${{ secrets.PRODUCTION_DATABASE_URL }}
steps:
- uses: actions/checkout@v4
- name: Gerar fixtures
run: |
curl -s "https://fakeforge.com.br/api/generate?type=pessoa&quantity=100&format=json" \
> tests/fixtures/pessoas.json
- name: Seed banco de testes
run: npm run db:seed
- name: Executar testes
run: npm testGerar fixtures na build, nunca fazer dump de produção
A geração em build time resolve dois problemas: nenhum dado real entra no pipeline e as fixtures ficam registradas como artefato rastreável. Guarde o artefato por 30 dias para debugging, mas nunca promova para o próximo ambiente sem regeração.
Auditoria de acesso ao banco de testes
Liste quem tem credenciais do banco de testes com a mesma disciplina que lista acesso à produção. Banco de teste com dados mascarados que vazam para notebook pessoal ainda é incidente de segurança se os dados permitem reidentificação.
---
API de dados sintéticos como dependência de projeto
Chamar uma API vs. biblioteca local: trade-offs
| Critério | API externa (FakeForge) | Biblioteca local |
|---|---|---|
| Atualização de regras (ex: CNPJ alfanumérico) | Automática | Requer atualização de dependência |
| Disponibilidade offline | Não | Sim |
| Rastreabilidade de origem | Via log de chamada | Nenhuma |
| Volume de geração | Limitado por plano | Ilimitado local |
| Manutenção do algoritmo | Terceiro | Seu time |
Para equipes com alto volume de geração em CI, os planos da API partem de R$29/mês com 10.000 chamadas/dia.
Geração em tempo de build x geração em tempo de execução
Geração em build time é preferível para estabilidade: o mesmo artefato roda em todos os ambientes do pipeline. Geração em execução é útil para testes de stress onde volume e diversidade importam.
Controle de volume: quantos registros seu pipeline realmente precisa
Equipes tendem a supersuprir fixtures "por precaução". 20 registros cobrem a maioria das combinações de edge case em testes unitários. 500 cobrem integração com paginação e filtros. Acima disso, avalie se o teste em questão é de carga, que tem requisitos diferentes de dados.
---
Documentação de conformidade: o que registrar
Mapeamento de dados (ROPA) inclui ambientes de teste?
Sim. O Registro das Operações de Tratamento (ROPA), exigido pelo Art. 37 da LGPD e pelo Art. 30 do GDPR para controladores com obrigação espelhada, deve incluir todos os ambientes onde dados pessoais transitam. Se o banco de testes tem dados reais ou pseudonimizados, ele entra no ROPA.
Evidências para auditoria: fixture origin, anonimização aplicada, data
Para cada ambiente de teste, documente: origem dos dados (sintético/mascarado), técnica aplicada (geração sintética/mascaramento campo a campo), data de geração e quem executou. Um arquivo fixtures/README.md com essas informações já satisfaz auditoria inicial da ANPD.
Relatório de Impacto à Proteção de Dados (RIPD): quando o teste obriga
O RIPD (Art. 38 da LGPD) é obrigatório para tratamentos que podem gerar risco aos titulares. Testes que usam dados reais de categorias sensíveis (saúde, biometria, dados financeiros detalhados) provavelmente obrigam RIPD. Testes com dados sintéticos não tratam dados pessoais e não precisam de RIPD.
---
Resumo
- Dados reais em teste são tratamento de dados pessoais sem base legal válida. Anonimização desde a origem é a única saída que elimina o problema pela raiz.
- Pseudonimização não remove o dado do escopo da LGPD (Art. 13, §4º). Hash reversível ainda é dado pessoal.
- CPF, CNPJ, PIX e cartões precisam de algoritmo correto (mod-11, Luhn) para não travar validações antes de qualquer lógica de negócio ser testada. Geradores como /gerador-cpf e /gerador-cnpj resolvem isso sem código extra.
- CNPJ Alfanumérico entra em vigor em 01/07/2026. Qualquer regex
\d{14}vai rejeitar CNPJs novos. Atualize fixtures e validadores agora usando /gerador-cnpj-alfanumerico. - Pipeline de CI/CD deve gerar fixtures na build, nunca promover dump de produção. Artefato gerado em build time é rastreável e não contém dados pessoais.
- Documente a origem dos seus fixtures (sintético vs. mascarado, data, responsável). Uma linha por ambiente no ROPA já coloca seu time à frente de 90% das equipes em uma auditoria da ANPD.
Perguntas frequentes
Staging com dados reais é tão arriscado quanto produção?+
Mais arriscado, na verdade. Staging tem menos controle de acesso (estagiários, freelancers), então a exposição é maior. A LGPD não diferencia ambiente. Se o dado é real e foi copiado sem finalidade legítima, é incidente independente da camada. Use sintético em staging também.
Se descobrirmos que usamos dados reais, precisamos notificar a ANPD?+
Só se houve acesso não autorizado confirmado. Usar seu próprio dado de produção em teste da sua empresa não é acesso não autorizado. Porém, se o dump vazou (e-mail, GitHub público), aí sim: comunicar à ANPD em até 72h (Resolução CD/ANPD 2/2022). Documentar o incidente internamente já.
FakeForge tem limite de requisições no plano gratuito?+
A interface web é livre. Endpoints da API entram nos planos pagos a partir de R$29/mês com 10.000 chamadas/dia. Para fixtures em CI/CD local com volume baixo (até 100 registros), a chamada GET simples pode ficar dentro de quotas de rate limit. Confira `/pricing` antes de escalar.
Posso usar fixture com CPF válido mas endereço aleatório?+
Não. CPF gerado sinteticamente é ok. Mas se você pega endereço real de uma API de CEP e combina com CPF sintético, criou um pseudo-registro potencialmente reidentificável (CEP+bairro+nome = rastreável). FakeForge já correlaciona: use pessoa completa ou implemente a correlação localmente.
Como validar que meu seed de teste realmente cobre os edge cases?+
Gere 20+ registros com FakeForge, mas priorize casos deliberados (CPF mod-11 limítrofe, CEP de fronteira, DDD raro). Seed determinístico permite reruns idênticos. Combine seed gerado com fixtures hand-coded para edge cases. Cobertura ≠ aleatoriedade. Veja `beforeAll` no artigo para factory padrão.