Escalar dados de teste entre países parece, no começo, um problema de volume: mais países, mais arquivos, mais exemplos. Na prática, o gargalo aparece em outro lugar. O que trava uma base que passou de cinco para cinquenta contextos não é a quantidade de dado, e sim o fato de que ninguém sabe mais quais asserções valem para quem. Este texto trata dessa passagem.
O que exatamente fica difícil quando o número cresce?
Ficam difíceis três coisas, e nenhuma delas é digitar mais dados. A primeira é a atribuição: cada verificação nova precisa de um responsável, e sem atribuição ela vive até a primeira falha e depois é desativada por alguém com pressa.
A segunda é a atribuição inversa: quando um país muda, descobrir quais verificações dependem dele. Em uma base pequena, a resposta está na memória da equipe. Em uma base grande, a memória falha, e a única forma de responder é a estrutura do conjunto.
A terceira é a interpretação da falha. Quando o resultado de uma execução tem dezenas de erros, a equipe precisa saber quais apontam para um defeito de modelo e quais apontam para um dado desatualizado em um país específico. Sem essa separação, os dois casos recebem o mesmo tratamento, e o tratamento errado é sempre mais caro.
Separar invariantes de listas de exceção
A estrutura que resolve as três dificuldades é dividir as verificações em duas famílias com significados distintos. As invariantes são afirmações que precisam valer para todo contexto do conjunto, sem exceção. A lista de exceções reúne o que difere de país para país, item por item, com o motivo declarado.
O valor dessa divisão está na interpretação. Uma invariante que falha indica que o modelo está errado, porque o modelo afirmou algo universal e o mundo discordou. Uma exceção que falha indica que o cadastro daquele país está incompleto ou desatualizado. As duas exigem ações diferentes: a primeira pede revisão de desenho, a segunda pede revisão de dado.
| Família | O que afirma | Falha significa | Ação típica |
|---|---|---|---|
| Invariante | Vale para todos os contextos | Modelo incorreto | Revisar desenho |
| Exceção declarada | Um país difere de um jeito específico | Cadastro velho | Revisar dado |
| Verificação de forma | Estrutura do conjunto se mantém | Conjunto inconsistente | Corrigir conjunto |
Exemplos de invariantes que costumam se sustentar: cada contexto tem uma chave única e estável; o conjunto de campos de cada contexto é enumerável; a ordenação de exibição é determinística; nenhum valor de campo é descartado em silêncio. Nenhuma dessas afirmações depende de qual país é.
A lista de exceções precisa ser explícita e revisável
Uma exceção guardada apenas no código é invisível para quem revisa dado, e uma exceção guardada apenas em documento não é verificável pela máquina. O meio-termo produtivo é uma tabela única, legível pelos dois lados.
Cada linha diz três coisas: qual contexto, qual afirmação não se aplica a ele, e por quê. O motivo é a parte mais importante, porque é o que impede que a exceção seja removida por engano. Uma linha com motivo fraco é um candidato natural a revisão na próxima auditoria.
Vale ainda separar a exceção da condição de exibição. Uma diferença de rótulo na tela não é exceção de dado; é decisão de apresentação. Misturar as duas tabelas transforma qualquer mudança de texto em alteração de verificação.
Como tornar a geração reproduzível
Uma base de dados de teste só tem valor comparativo se duas execuções da mesma entrada produzirem o mesmo resultado. Sem isso, a diferença entre a execução de ontem e a de hoje não pode ser atribuída a uma mudança no sistema, porque pode ser sorteio.
Reproduzir exige três coisas. Primeiro, uma semente explícita, registrada na saída de cada execução, para que qualquer pessoa possa repetir o mesmo conjunto. Segundo, entradas declaradas, e não descobertas de fontes que mudam entre execuções. Terceiro, ordenação estável na geração, porque uma ordem que varia produz conjuntos diferentes a partir do mesmo material.
Vale também registrar a versão do conjunto de países usada na geração, ligando este texto à versão que o gerou. Sem esse vínculo, um resultado antigo não pode ser reinterpretado depois, e a comparação entre execuções perde sentido.
Quando usar amostragem em vez de conferência total?
A conferência total deixa de ser viável em algum ponto entre dezenas e centenas de contextos, e tentar mantê-la produz um efeito conhecido: a verificação completa existe, mas ninguém a lê, e as falhas se acumulam até que ela seja desativada.
A amostragem por camadas resolve isso quando as camadas têm significado. As camadas naturais já estão no conjunto: o agrupamento regional, o nível de prioridade e a lista de exceções. A amostra precisa conter, em cada execução, pelo menos um item de cada camada, para que nenhuma família de comportamento fique sem representação.
O ponto delicado é o tamanho dos grupos pequenos. Se um grupo tem poucos itens, a amostragem aleatória pode não pegá-lo nunca. A resposta é tratar esses grupos como obrigatórios, e não como amostra: eles são poucos justamente porque são casos de fronteira.
Quais verificações rodar ao adicionar um país?
O procedimento que economiza mais trabalho é rodar o conjunto inteiro de invariantes mais a lista de exceções, em vez de revisar a ficha manualmente. Isso transforma a inclusão de um país em uma execução, e não em uma tarefa de leitura.
O roteiro tem quatro passos. Primeiro, todas as invariantes devem passar; uma falha aqui não é problema do país novo, é problema do modelo que a entrada expôs. Segundo, a lista de exceções deve ser atualizada com o que aquele contexto tem de específico, incluindo a ausência de campos. Terceiro, a geração deve continuar reproduzível com a nova entrada. Quarto, as amostras das camadas precisam ser revistas, porque um país novo pode mudar a composição de um grupo pequeno.
Vale também registrar a data de inclusão e a versão do conjunto, para que o histórico de execuções continue legível.
Para quem desenvolve: a lista de exceções pertence ao versionamento
A recomendação final é curta: a lista de exceções é código de projeto, e deve viver no mesmo lugar que o resto da configuração versionada. Ela explica por que o comportamento difere, e essa explicação precisa de histórico.
Na prática, isso significa três hábitos. Primeiro, toda exceção entra por revisão, com motivo escrito. Segundo, nenhuma exceção é removida sem que a verificação correspondente passe a valer. Terceiro, o conjunto de invariantes é pequeno e revisado periodicamente, porque uma invariante que ninguém entende acaba sendo desativada na primeira falha difícil.
Se você ainda está no começo dessa passagem, medir o estado atual é o passo anterior: a lista de cobertura de dados por país mostra como registrar o que já existe. Quando o assunto é manter a base correta ao longo do tempo, o texto sobre atualidade dos dados de país trata de fontes e datas. E a referência de formatos, organizada por país, está na página de formatos de endereço e identidade por país.
Aviso sobre os exemplos: as invariantes, as exceções e as camadas de amostragem apresentadas aqui são um esqueleto ilustrativo, montado para mostrar como a estrutura se organiza. Não correspondem ao conjunto de verificações de nenhum sistema real nem devem ser copiadas como especificação pronta.