Como um arnês de paridade comprova uma reescrita
Um arnês de paridade reproduz tráfego real, compara saídas exatas, controla variações e expõe erros discutidos do sistema antigo.

Uma reescrita está pronta quando se comporta como o sistema que substitui diante das entradas que importam. Uma arquitetura limpa, testes unitários aprovados e telas familiares não comprovam que o novo sistema lance os mesmos totais de fatura, escolha a mesma base tributária ou rejeite o mesmo ajuste malformado. Um arnês de paridade comprova. Ele envia a mesma solicitação gravada aos dois sistemas, captura cada resultado observável, normaliza apenas os campos autorizados a variar e produz uma diferença que um responsável consegue explicar.
Isso parece um teste de regressão comum até entrarem dinheiro, datas, estado e efeitos colaterais. Então a comparação simples deixa de funcionar. O aplicativo antigo pode consultar o relógio no meio de um cálculo, depender da ordem dos registros, arredondar depois de cada linha, reutilizar uma taxa de câmbio desatualizada ou gravar cinco linhas antes de devolver uma resposta. Alguns desses comportamentos são requisitos. Outros são acidentes dos quais os usuários passaram a depender. Outros são bugs. O arnês precisa distingui-los sem esconder provas inconvenientes.
Eu trato paridade como um argumento de aceitação, não como uma porcentagem em um painel. O argumento tem quatro partes: a entrada reproduzida representa a produção, as duas execuções começam de estados equivalentes, a política de comparação é explícita e cada diferença aceita tem responsável e motivo. Se qualquer parte for vaga, um resultado verde diz muito pouco.
Como a paridade difere da regressão comum
Um arnês de paridade compara duas implementações do mesmo comportamento. Uma suíte de regressão compara uma implementação com expectativas escritas por pessoas. Essa distinção muda o que cada teste pode descobrir. Um teste unitário confirma que uma função de juros reescrita corresponde à fórmula escolhida para o teste. Ele não informa que o sistema antigo trunca a taxa diária antes da capitalização, a menos que alguém já conhecesse essa peculiaridade e a codificasse. Reproduzir a mesma conta nos dois sistemas revela a diferença imediatamente.
O sistema antigo funciona como especificação executável, mas não é infalível. Tratá-lo como oráculo transforma sua saída em prova, não em verdade. O arnês deve informar que o legado retornou 104,17 e a reescrita retornou 104,18. Um responsável pelo produto, controlador financeiro ou dono de domínio nomeado decide se o centavo pertence ao contrato ou a um defeito. O mecanismo de teste não pode tomar essa decisão política arredondando silenciosamente os dois valores até que coincidam.
Os testes de regressão continuam necessários. Eles isolam regras, cobrem limites sintéticos e são rápidos o bastante para cada commit. A paridade cobre combinações que ninguém lembrou de descrever: uma linha de valor zero após uma nota de crédito, um cliente com dois calendários de cobrança ou um programa RPG que trata espaços de modo diferente de zeros. Mantenha os dois. Depois que uma diferença for julgada, transforme a decisão em um teste de regressão focado para a equipe não precisar redescobri-la em outra grande reprodução.
O arnês também compara mais do que a resposta visível. Em uma transação, o contrato observável pode incluir mutações no banco, arquivos emitidos, mensagens de fila, lançamentos contábeis, códigos de status, categorias de erro e ordenação. Se o substituto devolve o total certo, mas o lança no período contábil errado, a paridade apenas da resposta concede uma aprovação perigosa. Defina a fronteira de observação antes de gravar tráfego e inclua todo efeito que outro sistema ou uma pessoa possa ver.
Tráfego gravado precisa de um contrato de reprodução
Uma gravação útil contém informação suficiente para reproduzir a intenção sem copiar uma pilha descontrolada de logs. Logs brutos de acesso raramente bastam. Podem omitir corpos das solicitações, identidade autenticada, estado de sessão, cabeçalhos que selecionam uma regra de negócio ou a sequência que criou o estado atual do banco. Também podem conter segredos que jamais devem entrar em um armazenamento de teste.
Use um envelope de reprodução versionado. Ele diz o que chegou, qual contexto afetou o comportamento, qual checkpoint de estado o caso espera e quais saídas o arnês inspecionará. Um formato prático é:
{
"case_id": "close-004812",
"captured_at": "2026-01-31T23:58:42Z",
"operation": "POST /accounts/close",
"identity_ref": "role:month_end_operator",
"state_checkpoint": "ledger-2026-01-31-r7",
"request": {"account_id": "A1842", "period": "2026-01"},
"observe": ["response", "ledger_entries", "outbox"]
}
Armazene referências a identidades e segredos, nunca credenciais ativas. Substitua campos pessoais somente por um mapeamento determinístico, pois anonimização aleatória pode destruir junções e significado de negócio. Se o cliente 842 aparece em uma solicitação, numa linha contábil e numa tabela de endereços, o fixture sanitizado deve manter essas referências conectadas. Preserve comprimentos e classes de caracteres quando a validação depender deles.
A amostragem merece uma política escrita. Uma fatia aleatória de solicitações comuns oferece volume, mas costuma perder casos raros com risco financeiro ou operacional. Combine uma amostra de produção com estratos deliberados: tipo de operação, sucesso e falha, valores altos e zero, limites de calendário, codificações incomuns, jobs longos e cada ramo ligado a dinheiro ou direito de acesso. Grave sessões de várias etapas como casos ordenados quando chamadas posteriores dependerem das anteriores.
Mantenha a captura original imutável. Derive fixtures sanitizados e reproduzíveis com transformações versionadas e registre a versão da transformação em cada execução. Caso contrário, uma mudança no sanitizador pode alterar a entrada enquanto a equipe pensa que está avaliando uma mudança no programa. O acesso às capturas deve ser restrito, a retenção deve ser finita e um caso com falha deve expor identificadores por diagnósticos controlados em vez de despejar registros completos nos logs de CI.
Estado inicial equivalente faz parte do teste
A mesma solicitação contra dados diferentes não comprova nada. Antes de cada unidade de reprodução, as duas implementações precisam de estado logicamente equivalente, incluindo tabelas de referência, configurações de recursos, posições de sequência, limites de lote e registros criados em etapas anteriores. Isso costuma ser mais difícil do que enviar a solicitação.
Escolha a menor fronteira de redefinição que preserve o significado. Um cálculo puro de cotação pode partir de um fixture compacto por caso. O fechamento de uma conta pode exigir um cenário ordenado com vários lançamentos anteriores. Um lote noturno pode precisar de checkpoint completo do banco e fila controlada. Redefinir todo o ambiente antes de cada solicitação é lento. Reutilizar um banco mutável deixa os casos contaminarem uns aos outros. Agrupe casos em cenários independentes, redefina nas fronteiras e mantenha a ordem das solicitações dentro de cada grupo.
Não exija esquemas físicos idênticos. Um serviço modernizado com Postgres não deve imitar arquivos VSAM ou um arquivo físico do AS/400 apenas para facilitar a comparação. Crie adaptadores de estado que expressem os mesmos fatos de negócio em cada representação. Depois compare resultados de negócio observáveis, não layouts internos de tabela. Paridade de arquitetura anularia o objetivo da reescrita.
A preparação do estado deve incluir valores que as equipes esquecem: data de negócio, banco de fusos horários, localidade, metadados de moeda, modo de arredondamento, tabelas fiscais, taxas de câmbio, sementes de sequência e contexto de autorização. Fixe essas dependências a uma versão do fixture. Se o job legado lê uma tabela de taxas pela data de vigência e a reescrita usa a linha mais recente de hoje, JSONs de solicitação idênticos ainda conduzem a problemas diferentes.
Verifique a preparação em vez de confiar no carregador. Antes de executar, calcule uma impressão digital semântica compacta, como contagens e hashes sobre registros de negócio canônicos. As impressões antiga e nova não serão idênticas byte a byte entre esquemas, mas podem afirmar fatos como 418 itens em aberto, a mesma soma do principal por moeda e o mesmo conjunto de identificadores de regras ativas. Uma falha de preparação deve interromper o caso como inválido, não aparecer depois como divergência do aplicativo.
Comparação exata começa com valores canônicos
Compare dinheiro como valores decimais com escala e moeda declaradas, nunca como strings formatadas ou aproximações binárias de ponto flutuante. A expressão «até o centavo» parece simples, mas equipes frequentemente comparam 12,3 com «12,30», convertem ambos por um tipo flutuante ou arredondam apenas o total final quando o programa antigo arredonda cada linha. O arnês precisa do contrato aritmético do domínio.
A IEEE 754 explica por que o ponto flutuante binário não representa exatamente muitas frações decimais. Isso não torna errado todo cálculo flutuante. Significa que um épsilon sem explicação é uma política ruim para paridade financeira. Analise saídas monetárias como coeficientes e escalas decimais e aplique a regra de negócio na mesma etapa do sistema de produção. Se o contrato manda arredondar cada linha de imposto para longe de zero, faça isso antes de somar. Se manda preservar quatro casas em uma taxa intermediária, compare esse valor quando observável ou adicione um diagnóstico focado.
A canonização deve remover ruído de representação e preservar o significado. Pode normalizar um timestamp para UTC, ordenar um conjunto explicitamente não ordenado por campos de negócio estáveis, tratar campos JSON opcionais ausentes conforme o contrato da API e decodificar um valor de largura fixa preenchido. Não pode mudar a caixa de identificadores sensíveis, ordenar uma sequência visível aos usuários, descartar linhas duplicadas ou transformar todo erro em falha genérica.
Torne a política legível como dados, em vez de enterrá-la no código do comparador:
rules:
- path: response.total_due
type: decimal
scale: 2
tolerance: 0
- path: response.generated_at
type: timestamp
mode: injected-clock
- path: outbox[*].headers.trace_id
mode: ignore
reason: generated transport identifier
- path: response.allocations
mode: ordered
Essa política impede que uma limpeza inocente amplie a tolerância da suíte toda. Exija motivo para cada caminho ignorado e tolerância diferente de zero. Revise mudanças na política como código de produção, pois um comparador consegue apagar um defeito com mais eficiência do que qualquer reescrita consegue criar um.
Relate diferenças no campo de negócio, não como dois blocos JSON gigantes. Um resultado útil diz invoice.lines[7].tax: legacy 1.34, rewrite 1.35, seguido da regra aplicável e da versão do fixture. Inclua contagens agregadas, mas nunca deixe 99,9 por cento de correspondência esconder qual décimo falhou. Um desconto salarial errado pesa mais do que milhares de verificações de saúde idênticas.
Controle o não determinismo antes de ignorá-lo
A maior parte do não determinismo pode virar entrada. Injete um relógio, defina a semente aleatória, reserve identificadores, congele dados de referência e isole a concorrência. Quando os dois programas consomem os mesmos valores explícitos, o arnês testa comportamento em vez de comparar dois acidentes.
Classifique cada campo variável em um de quatro grupos. Valores controlados recebem a mesma entrada nos dois sistemas. Valores canônicos diferem na representação, mas se reduzem ao mesmo significado. Valores ignorados não têm significado de negócio, como um identificador de rastreamento de transporte. Saídas estatísticas exigem outro teste, pois uma reprodução não comprova paridade para um modelo estocástico. Essa classificação é mais precisa do que uma lista global de ignorados e oferece aos revisores algo concreto para questionar.
O tempo causa a maioria das falhas evitáveis. Um processo pode ler o relógio ao receber a solicitação, no lançamento e outra vez ao formatar a resposta. Sobrescrever apenas o timestamp final deixa a lógica de limite de datas sem controle. Encaminhe cada leitura do relógio de negócio da reescrita por uma fonte injetável. No lado legado, execute em ambiente isolado com hora controlada quando seguro, intercepte seu provedor de tempo ou capture os valores usados e compare resultados de negócio derivados num cenário que não atravesse uma fronteira. Nunca altere o relógio de um host de produção compartilhado.
Identificadores gerados precisam de correlação em vez de igualdade quando não têm significado de domínio. Suponha que os dois sistemas criem um novo ID de sinistro e depois o usem em três linhas e um evento. Mapeie o ID legado para o novo no ponto de criação e confirme que todas as referências posteriores preservam a relação. Ignorar todos os IDs esconderia uma referência estrangeira quebrada. Exigir sequências iguais acoplaria a reescrita a um detalhe de implementação.
Concorrência exige testes repetidos e agendados, não normalização otimista. Se a ordem do resultado for irrelevante por contrato, compare um multiconjunto e ainda verifique multiplicidade. Se dois lançamentos disputam o mesmo saldo, force os dois entrelaçamentos com barreiras na leitura e na gravação disputadas. Uma tolerância ampla não desculpa atualizações perdidas. Mantenha testes de carga e resistência separados da paridade semântica, mas leve qualquer falha encontrada a um cenário de paridade pequeno e reproduzível.
Efeitos colaterais exigem captura, não duplicação
Uma reprodução não pode enviar pagamentos, e-mails, trabalhos de impressão ou mensagens a parceiros reais. Substitua a fronteira por um gravador que aceite o mesmo comando, devolva uma confirmação controlada e armazene uma representação canônica para comparação. A meta é comprovar que o novo sistema pretendia o mesmo efeito, não executar o efeito duas vezes.
Coloque gravadores na última fronteira sob seu controle. Capturar uma chamada de função interna pode passar mesmo quando serialização, roteamento ou cabeçalhos estão errados. Capturar além da fronteira pode afetar terceiros. Para um broker de mensagens, grave o tópico final, cabeçalhos de negócio, campo de particionamento quando significativo e payload após serialização. Para uma interface de arquivo, capture bytes e uma visão de negócio analisada quando larguras fixas, codificações ou finais de linha fizerem parte do contrato.
Efeitos no banco precisam de comparação consciente da transação. Tire um snapshot anterior das entidades relevantes, execute o caso e calcule o delta posterior. Compare inserções, atualizações, exclusões e invariantes entre as representações. Não compare diretamente timestamps de auditoria nem IDs substitutos, a menos que consumidores dependam deles. Compare se débitos equilibram créditos, se há uma linha de outbox por ação confirmada e se o rollback não deixa mudança parcial de negócio.
Falhas também são saídas. Compare classe de falha, status, capacidade de recuperação e efeitos. O texto exato do erro legado pode não merecer preservação, principalmente se a reescrita retorna erro estruturado, mas chamadores podem depender de um código ou sinal de repetição. Escreva essa regra de compatibilidade. Um substituto que transforma uma falha permanente de validação em erro de servidor repetível pode causar mais dano do que uma diferença visual de um centavo.
O gravador deve expor tentativas duplicadas. Durante repetições, compare a idempotência na sequência completa: primeira solicitação, confirmação perdida, solicitação repetida e estado final. Dois comandos de saída idênticos não são inofensivos só porque um ambiente de teste posterior aceitou ambos.
Uma divergência precisa de trilha de decisão
Cada divergência deve seguir um fluxo pequeno e explícito: reproduzir, localizar, classificar, atribuir responsável e codificar a decisão. Sem essa trilha, equipes perseguem timestamps inofensivos por dias ou ignoram diferenças financeiras para proteger um prazo.
Comece reduzindo a reprodução que falhou. Preserve o checkpoint, remova registros sem relação e reduza a sequência até a diferença permanecer. Depois inspecione o primeiro valor observável divergente, não o total final. Uma diferença de um centavo na fatura pode começar num arredondamento por linha. Vinte campos posteriores apenas a repetem. Guarde o caso reduzido junto do arnês para que rode em toda mudança.
Use um conjunto curto de classificações:
- Defeito da reescrita: a nova implementação viola comportamento legado aceito.
- Defeito do arnês: estado, captura, normalização ou observação está errada.
- Correção aprovada: o comportamento legado está errado e um responsável autoriza um novo resultado.
- Mudança de contrato: a organização altera deliberadamente o comportamento além de corrigir um defeito.
- Não resolvido: ainda faltam provas ou responsabilidade, portanto a entrega continua bloqueada para o caso.
Um registro de aprovação deve nomear caso, campo, valor legado, valor novo, justificativa, aprovador, data da decisão e o teste de regressão que passa a definir o comportamento esperado. Evite dispensas livres como «problema de arredondamento aceito». Seis meses depois, ninguém sabe se cobria uma jurisdição tributária ou todos os cálculos. Faça exceções amplas expirarem e proíba curingas sem motivo limitado.
Um artefato de falha útil cabe numa revisão sem expor o registro completo de produção. Inclua entradas sanitizadas, impressão semântica do estado, duas saídas normalizadas, diff estruturado, versão da política e comando de reprodução. Esse pacote permite ao engenheiro reproduzir o resultado enquanto o responsável de domínio revisa a consequência real para o negócio.
Quando o sistema antigo erra, preserve a prova
Defeitos legados conhecidos devem virar divergências aprovadas, nunca truques no comparador. Primeiro comprove que a reescrita diverge. Depois comprove por que o resultado antigo viola a regra escolhida. Por fim, registre quem detém a decisão de mudar o comportamento observável. Isso separa autoridade técnica de migração e autoridade de negócio.
O conselho popular «iguale primeiro, corrija depois» só ajuda quando o depois é real. Ele reduz variáveis simultâneas e facilita o raciocínio sobre a migração. Está errado quando entrega uma cobrança excessiva conhecida, recria um caminho inseguro de autorização ou consolida dados corrompidos porque ninguém planejou a segunda mudança. Gravidade e reversibilidade decidem a ordem. Preserve peculiaridades inofensivas temporariamente se isso reduzir o risco de entrega. Corrija comportamento prejudicial antes da virada, com aprovação e comunicação explícitas.
Passe correções aprovadas por duas afirmações. A afirmação de paridade documenta a diferença intencional: o legado produz X, o substituto produz Y. A afirmação de regressão de negócio comprova Y a partir de regra ou exemplo independente. Se o lado legado for removido depois, o segundo teste sobrevive como especificação duradoura. Isso também impede que um futuro mantenedor «conserte» a reescrita de volta ao defeito antigo após ver um caso vermelho.
Dados históricos podem carregar o defeito. Código correto ainda pode divergir de relatórios antigos porque saldos, indicadores de status ou campos derivados armazenados já contêm resultados errados. Decida se vai migrar, recalcular, colocar em quarentena ou preservar cada classe de registro afetada. Ensaie essa política de dados no mesmo checkpoint da reprodução. Paridade de código sem destinação dos dados deixa incompleto o argumento de virada.
Comunique o comportamento alterado na fronteira em que usuários ou sistemas dependentes o percebem. Um valor corrigido pode exigir relatório de conciliação. Validação mais estrita pode revelar registros aceitos silenciosamente pelo sistema antigo. Uma correção de autorização pode invalidar um fluxo. A trilha de decisão deve indicar a resposta operacional, não apenas a justificativa aritmética.
O executor legado precisa de interface estável
O arnês deve invocar o sistema antigo pela fronteira estável mais estreita que ainda exercite o comportamento real. Um endpoint HTTP é conveniente quando já existe, mas muitos caminhos legados começam com arquivo de lote, registro de fila, transação de terminal ou procedure armazenada. Envolva essa entrada com um executor que aceite o envelope, estabeleça contexto, espere a conclusão e devolva observações capturadas num formato versionado. Não reescreva lógica de negócio no adaptador. Cada regra copiada cria outra implementação que pode divergir.
Trate a saúde do executor separadamente da saída do aplicativo. Timeout, região indisponível, carregamento de fixture com falha ou defeito do gravador torna o caso inconclusivo. Isso não significa que o legado retornou erro e certamente não conta como paridade. Use um envelope de resultado que distinga completed, application_failure e infrastructure_failure, e anexe logs de job ou códigos diagnósticos sob retenção controlada. Essa distinção impede que infraestrutura instável infle a aparente taxa de correspondência.
O isolamento de recursos importa quando a plataforma antiga tem estado global. Duas reproduções paralelas podem compartilhar arquivos temporários, nomes de jobs, geradores de sequência ou uma tabela de trabalho que o código produtivo supõe ter um escritor. Trave esses recursos explicitamente ou aloque namespaces isolados quando a plataforma permitir. Se for impossível isolar, serialize o cenário afetado e declare isso nos metadados. Um arnês rápido que muda o comportamento medido fornece provas piores do que um mais lento e honesto.
Versione executor, adaptadores, política de comparação, fixtures e build candidato em cada resultado. Um identificador de reprodução deve bastar para reconstruir os cinco. Guarde artefatos por conteúdo quando possível para o revisor provar que um relatório posterior usa as mesmas saídas normalizadas. Proteja pacotes finais de aceitação conforme os controles de mudança existentes. O arnês não precisa de nova burocracia, mas suas provas devem durar pelo menos tanto quanto a aprovação que sustentam.
Por fim, teste o arnês com diferenças implantadas. Mude um centavo, remova um registro de outbox, troque duas alocações ordenadas, desloque a data de negócio e force um vazamento de rollback num fixture controlado. Cada mutação deve produzir a falha de campo esperada. Equipes testam código de aplicativo constantemente e presumem que o comparador funciona. Um comparador que nunca demonstrou sua sensibilidade é uma parte não testada da migração.
A prova de entrega deve resistir melhor que uma taxa
Um critério confiável de entrega nomeia o comportamento coberto e a incerteza restante. Não diz apenas que 98 por cento dos casos passaram. Relate cobertura por operação e classe de risco, quantidade de correspondências exatas, correções aprovadas, falhas do arnês, diferenças não resolvidas e fronteiras não testadas. Mostre se a amostra inclui fechamento de período, rollback, repetição, entrada malformada, transações de alto valor e os formatos de dados mais antigos ainda aceitos.
Mantenha o critério estrito: nenhuma diferença não resolvida numa classe crítica, nenhum efeito inesperado, nenhuma mudança na política escondida no build candidato e nenhuma falha de preparação contada como sucesso. Divergências de menor risco podem seguir uma decisão documentada, mas continuam aparecendo na prova. Um denominador que exclui reproduções interrompidas em silêncio é fraude de planilha.
Execute o mesmo corpus mais de uma vez. Repetibilidade detecta tempo descontrolado, ordem, estado compartilhado e vazamento ambiental. Depois reproduza uma captura recente reservada que os desenvolvedores não usaram ao ajustar a reescrita. Um corpus pode se tornar alvo de sobreajuste como uma suíte unitária. A reserva não precisa ser enorme. Precisa de procedência representativa e protegida e método de amostragem documentado.
Na virada, execução em sombra pode somar provas se o sistema permitir com segurança. Envie uma cópia de leituras ou comandos ativos elegíveis ao substituto, suprima seus efeitos e compare resultados fora do caminho do usuário. Nunca deixe os dois lados confirmarem uma operação em sombra. Monitore privacidade, capacidade e alterações temporais introduzidas pelo próprio caminho.
A CodeHero usa tráfego de produção gravado e um arnês de paridade para manter sistemas reescritos em Go, Rust e TypeScript fiéis ao comportamento original enquanto muda a arquitetura. Em um projeto entregue em menos de 30 dias, essa prova precisa ser projetada na entrada, não montada na reunião de entrega.
O pacote de aceitação também deve expor o que a reprodução não comprovou. Liste operações sem captura utilizável, integrações representadas apenas por um stub, períodos de dados ausentes dos fixtures e padrões de concorrência testados somente sob carga. Para cada lacuna, nomeie a prova compensatória, como uma suíte de regressão focada, uma consulta de conciliação, um ensaio preparado com operadores ou uma observação limitada depois da virada. Não transforme esses controles em afirmações de paridade. Eles respondem a outra pergunta e precisam manter esse rótulo. Assim, quem aprova a entrega julga um risco limitado em vez de supor que muitos casos cobrem todos os caminhos. Mantenha esse registro de lacunas anexado ao resultado final, pois ele vira o primeiro plano de teste para monitoramento em produção e para o próximo ciclo de captura. Se uma operação não representada aparecer na sombra, acrescente-a ao corpus com a procedência intacta. A prova melhora quando novos casos ampliam uma fronteira declarada. Ela perde credibilidade quando a equipe muda em silêncio o significado de cobertura.
Um arnês de paridade conquista confiança pelas diferenças que se recusa a esconder. Torne entradas reproduzíveis, estado equivalente, aritmética explícita, campos variáveis classificados e exceções atribuídas. Assim, o último caso vermelho é prova útil, não um obstáculo a ser pintado de verde.
Perguntas frequentes
O que é um arnês de paridade numa reescrita?
Ele executa o mesmo caso capturado no sistema legado e no substituto e compara cada resultado de negócio observável. Inclui estado inicial, regras de normalização, efeitos colaterais e registro de decisão para diferenças.
Quanto tráfego de produção devemos reproduzir?
Não existe porcentagem universal honesta. Amostre tráfego comum e acrescente operações raras, falhas, limites de valor e calendário, repetições e ramos que afetem dinheiro ou acesso.
Podemos usar logs de produção diretamente como fixtures?
Em geral, não. Logs omitem corpos, identidade, estado ou ordem e podem expor segredos. Crie envelopes versionados e sanitização determinística.
Valores monetários devem ter tolerância de comparação?
Comece com tolerância zero após analisar decimais e aplicar a regra de arredondamento declarada. Use tolerância diferente de zero só quando o contrato permitir e exija motivo naquele campo exato.
Como comparar IDs gerados entre dois sistemas?
Mapeie o ID legado para o novo na criação de cada objeto e confirme todas as referências posteriores. Ignorar IDs esconde vínculos quebrados. Exigir sequências iguais acopla os sistemas sem necessidade.
Como tratar timestamps em testes de paridade?
Injete o mesmo relógio de negócio quando possível e normalize representação, como fuso, somente se o significado continuar intacto. Ignorar todos os timestamps pode ocultar erros em datas de lançamento, expiração ou juros.
E se o sistema legado tiver um bug conhecido?
Registre uma correção aprovada com valor antigo, novo, justificativa, responsável e data. Mantenha uma afirmação de paridade que documenta a diferença e um teste independente que comprova a regra corrigida.
Um teste de paridade deve comparar tabelas do banco?
Compare mudanças de estado de negócio e invariantes, não layouts idênticos. Uma arquitetura moderna pode armazenar de outra forma e ainda produzir os mesmos fatos confirmados, mensagens e comportamento visível.
Como testar efeitos externos com segurança?
Substitua fronteiras de pagamento, e-mail, arquivo, impressão e parceiros por gravadores que capturem o comando final sem executá-lo. Compare payload, roteamento, multiplicidade, resultado transacional e repetições.
Quando a prova de paridade basta para a virada?
Quando operações críticas e casos de risco estão representados, execuções são repetíveis, efeitos correspondem e nenhuma diferença crítica fica sem solução. Publique correções aprovadas e fronteiras não testadas junto dos sucessos.