Validações brasileiras em .NET, com mensagens claras em português e testes levados a sério.
CPF · CNPJ alfanumérico (2026) · CEP · telefone · e-mail · chave PIX · boleto · cartão · placa · RENAVAM · PIS
Todo sistema brasileiro valida CPF, CNPJ, CEP e boleto, e quase sempre com um trecho copiado da internet: sem testes, com mensagem genérica ("inválido") e desatualizado. Duas mudanças recentes quebram muito código por aí:
- CNPJ alfanumérico: desde julho de 2026 a Receita emite CNPJs com letras (
12.ABC.345/01DE-35). Quem valida só dígitos passa a recusar empresas reais. - Fator de vencimento do boleto: chegou a 9999 em 21/02/2025 e recomeçou em 1000. Quem calcula a data a partir de 1997 lê vencimentos em 2049.
O Confere trata os dois casos e explica cada erro: "O dígito do 2º campo não confere. Confira a digitação."
| Tipo | Além de validar |
|---|---|
| CPF | Região fiscal pelo 9º dígito e máscara da LGPD (***.456.789-**) |
| CNPJ | Numérico e alfanumérico; matriz ou filial |
| CEP | UF pela faixa dos Correios |
| Telefone | Fixo ou celular, DDD, UF e formato internacional; aceita +55 e o 0 de longa distância |
Sugere a correção de domínios digitados errado (gmial.com → gmail.com) |
|
| Chave PIX | Descobre se é CPF, CNPJ, celular, e-mail ou aleatória |
| Boleto | Bancário (47) e de arrecadação (48), ou código de barras (44): banco, valor, vencimento e segmento |
| Cartão | Luhn e bandeira (Visa, Mastercard, Elo, Amex, Hipercard, Diners, Discover) |
| Placa | Antiga e Mercosul, com a conversão entre as duas |
| RENAVAM e PIS/NIS | Dígito verificador (e uma curiosidade: os dois cálculos são equivalentes) |
using Confere;
var r = Cpf.Validar("529.982.247-25");
r.Valido; // true
r.Formatado; // "529.982.247-25"
r.Detalhes["Região fiscal"]; // "ES e RJ"
Cnpj.EhValido("12.ABC.345/01DE-35"); // true
Boleto.Validar(linha).Detalhes["Vencimento"]; // "15/10/2026"
Validadores.Identificar("01310-100"); // [CEP]public class Cliente
{
[Required, Cpf] public string? Cpf { get; set; }
[Cep] public string? Cep { get; set; }
[Telefone] public string? Celular { get; set; }
[ChavePix] public string? Pix { get; set; }
}
// Erro: "CPF: Dígitos verificadores não conferem."| Verbo | Rota | O que faz |
|---|---|---|
| GET | /api/validar/{tipo}?valor= |
Valida e devolve formatado, detalhes ou o motivo do erro |
| POST | /api/validar/{tipo}/lote |
Confere até 1.000 valores: válidos, inválidos e repetidos |
| GET | /api/identificar?valor= |
Descobre o que o valor é |
| GET | /api/gerar/{tipo}?quantidade= |
Gera dados fictícios válidos para testes |
| POST | /api/exemplo/cliente |
Cadastro de exemplo validado pelos atributos |
Documentação completa no Swagger (/swagger). Limite de 120 chamadas por minuto por IP.
| O que é isso? | Conferência em lote |
|---|---|
![]() |
![]() |
| Boleto | Gerador de dados fictícios |
|---|---|
![]() |
![]() |
| Para devs (tema escuro) | Celular |
|---|---|
![]() |
![]() |
O desafio de origem deste projeto era sobre testes unitários, então a qualidade é o centro:
| Camada | O que garante |
|---|---|
| Referência independente | Os exemplos válidos dos testes vêm de tests/referencia/referencia.py, escrita direto das especificações (Receita, Febraban, Anatel, Luhn), com código diferente do C#. Assim a biblioteca não é testada contra ela mesma. |
| Testes de exemplo | Cada mensagem de erro, formato e detalhe, com casos válidos e inválidos. |
| Testes de propriedade (FsCheck) | Regras conferidas com centenas de entradas geradas: nenhum validador lança exceção com texto qualquer; todo valor gerado é válido; o Luhn pega qualquer dígito trocado; a máscara nunca revela as pontas do CPF. |
| Cobertura (coverlet) | 100% das linhas da biblioteca. O dotnet test falha abaixo de 95%. |
| Testes de mutação (Stryker.NET) | O código é alterado de propósito (> vira >=, "SP" vira ""...), e os testes precisam perceber. O CI falha abaixo de 80%. |
Com 100% de cobertura, a primeira rodada do Stryker deu 73%. Os testes executavam as tabelas e as fronteiras, mas não as conferiam:
- a tabela de 67 DDDs tinha só 8 conferidos: trocar a UF de qualquer outro passaria despercebido;
- o cálculo em módulo 11 dos boletos de arrecadação nunca tinha rodado (todos os exemplos usavam módulo 10);
- as fronteiras (cartão com exatamente 13 e 19 dígitos, e-mail com exatamente 254 caracteres, chave PIX de 77) não eram testadas;
- a regra do "ciclo mais próximo" do boleto parecia testada, mas os testes usavam como "hoje" a mesma data do computador.
Depois de testar as tabelas inteiras contra listas escritas de outro jeito (DDDs agrupados por UF, como na Anatel) e cobrir as fronteiras, a nota foi para 100%. Os poucos mutantes restantes são equivalentes (não mudam o comportamento) e estão marcados no código com o motivo.
dotnet test # 391 testes + portão de cobertura
cd tests/Confere.Tests && dotnet stryker # testes de mutação
python tests/referencia/referencia.py # confere a referência independenteCom um clique (Windows): dois cliques em Abrir Confere.cmd (ou no atalho Confere da Área de Trabalho). O navegador abre em http://localhost:5220.
Pelo terminal: pré-requisito .NET 9 SDK.
dotnet run --project src/Confere.Apisrc/Confere Biblioteca (pacote NuGet): validadores, atributos e catálogo
src/Confere.Api Minimal API + playground (HTML, CSS e JavaScript puro)
tests/Confere.Tests Exemplos, propriedades, tabelas e fronteiras (+ stryker-config.json)
tests/Confere.Api.Tests Integração da API
tests/referencia Implementação independente em Python
docs/ Lean Inception e telas
O escopo foi definido com Lean Inception: docs/lean-inception.md.
Este projeto nasceu do desafio "Implementando Validações de Testes Unitários com C#" da DIO. A entrega, com os TODO resolvidos e nota de mutação 100%, está em barbozadevti/trilha-net-testes-unitarios-desafio.







