Menú

Por qué tus direcciones de prueba y códigos postales no coinciden

Por qué la ciudad, la región, el código postal y el teléfono generados se contradicen entre sí, cómo detectar ese desajuste y cómo mantener los campos de dirección consistentes.

Publicado el

  • addresses
  • postal-codes
  • validation

Una dirección generada que falla en el checkout es una de las clases de fallo de prueba más irritantes, porque cada campo por separado parece correcto. La ciudad existe. El código postal tiene la cantidad de dígitos correcta. El número de teléfono lleva un código de área válido. Nada está mal, salvo que los tres pertenecen a lugares distintos.

El error aparece tarde y lejos del fixture: una API de envíos rechaza el destino, un validador de direcciones dice que la ciudad y el código postal no concuerdan, un cálculo de impuestos cae a una tasa por defecto, o un agente de soporte lee en voz alta una dirección que suena plausible y es incorrecta. Esta guía explica de dónde sale el desajuste, cómo medirlo en los datos que ya tienes y qué hacer para que no vuelva.

Qué es un desajuste entre dirección y código postal

Un desajuste es una contradicción entre dos campos de un mismo registro de dirección, donde cada campo es válido por separado. No es un valor mal escrito ni un formato equivocado: es una tupla imposible. El código postal cumple el patrón de su país y pertenece a una región real, la ciudad también existe, el teléfono también tiene la longitud correcta, pero las tres piezas describen lugares diferentes.

Esa definición tiene una consecuencia práctica importante: un desajuste no se detecta mirando un campo, se detecta mirando la relación entre campos. Cualquier verificación de una sola columna —una longitud, un patrón, un indicador de obligatorio— va a aprobar las tres piezas sin excepción. Por eso los datos generados de forma ingenua llegan tan lejos antes de romperse.

Conviene separar dos ideas que suenan parecidas. La primera es si un valor tiene el formato del país. La segunda es si los campos del registro concuerdan entre sí. La validación de formulario casi siempre prueba la primera y casi nunca la segunda, y es la segunda la que produce el fallo caro.

Cómo se producen los desajustes en un generador ingenuo

Los generadores ingenuos construyen una dirección campo por campo, y cada paso es defendible por separado aunque el producto no lo sea. El país se toma de una lista. La ciudad se toma de un conjunto global de nombres de ciudades, a veces filtrado por país y a veces no. El código postal se produce a partir de una expresión regular por país. El teléfono se arma con un código de país más dígitos aleatorios.

El problema es que los códigos postales no son cadenas aleatorias con una forma determinada: están asignados geográficamente. En Estados Unidos el primer dígito de un ZIP identifica un grupo de estados y los tres primeros identifican un centro seccional, así que un código que empieza por cero pertenece al noreste y no puede ser un código válido para una ciudad de California. En el Reino Unido la parte anterior al espacio identifica un área postal y un distrito, lo que restringe la localidad. En Canadá el primer carácter del forward sortation area identifica una provincia o territorio. Los dos primeros dígitos de Alemania identifican una región. Tratar el formato como la única restricción descarta justamente la información que hace que la tupla sea coherente. Los patrones de cada país están reunidos en formatos de código postal por país.

Los teléfonos fallan igual. Los planes nacionales de numeración asignan bloques de números por región, y la mayoría de los países esperan que quites el prefijo nacional de troncal antes de agregar el código de país. Un generador que concatena un código de país con un número que todavía lleva su cero inicial produce algo sintácticamente plausible y que nunca se puede marcar.

Cómo detectarlo en los datos que ya tienes

Las invariantes de tupla son verificables y detectan esto a bajo costo, sin necesidad de datos de referencia nuevos.

  • Un código postal, varias ciudades. Consulta por un código postal que aparezca con más de un puñado de ciudades. En datos reales un código postal cubre una ciudad o un conjunto pequeño de áreas de reparto, mientras que en datos generados de forma ingenua es una cadena aleatoria que las colisiones reparten entre muchas ciudades.
  • Vacíos imposibles. Varios países no tienen un sistema de código postal de uso cotidiano, así que un formulario que fuerza un valor en ese campo significa que el generador lo inventó. Si tus datos semilla traen un código postal para todos los países del mundo, algunos de esos son fabricaciones.
  • Lectura a mano de veinte filas. Suena poco serio y funciona: una persona detecta que una ciudad del sur emparejada con un código del noreste no tiene sentido, algo que una verificación de longitud nunca verá.
  • Longitudes de teléfono sospechosamente uniformes. Si todos los valores guardados tienen la misma longitud sin importar el país, el generador está rellenando dígitos en lugar de seguir un plan de numeración.

No todo desajuste es geográfico. Algunos son desacuerdos de formato que solo parecen problemas de datos. El código canadiense alterna letra y dígito, los Países Bajos ponen cuatro dígitos antes de dos letras, el Reino Unido mezcla ambos con un espacio interno significativo y el Eircode de Irlanda es alfanumérico y no ocupa el mismo lugar que un código numérico. Si un lado escribe el código canadiense sin espacio y el otro lo espera con espacio, la tupla es correcta y la validación igual falla. Normaliza ambos lados —quita separadores, pasa a mayúsculas, vuelve a insertar el separador canónico— antes de concluir que dos valores se contradicen. El procedimiento completo está en validación y normalización de direcciones.

Una comprobación de distribución atrapa lo que las muestras dejan pasar. Las revisiones por muestreo encuentran errores gruesos; una revisión de distribución encuentra los sutiles. En datos reales, la cantidad de códigos postales distintos por país sigue la asignación propia de ese país, y la población se concentra en unas pocas ciudades que explican la mayoría de las filas. Una selección uniforme entre todas las ciudades de un país produce datos que se ven mal en cualquier gráfico agregado y, peor, nunca ejercitan los caminos de código que asumen que cualquier ciudad puede aparecer en cualquier momento.

El desajuste es una familia, no un solo error

El síntoma que reporta la gente —el código postal y la ciudad no coinciden— no es un único fallo sino una familia, y cada miembro necesita su propio fixture, con un resultado esperado escrito al lado.

Miembro de la familia Resultado esperado
Código postal de otra región Rechazar en la validación, por la regla de relación
Código postal que no existe Rechazar en la consulta, contra los datos de referencia
Nombre de ciudad con diacríticos Aceptar después de normalizar a NFC
País sin sistema de código postal Aceptar con el campo vacío
Código postal extranjero pegado Decisión de política; no debe romper el formulario
Un código postal que cubre dos ciudades Aceptar: un código real puede cubrir varias

La última fila importa más de lo que parece. Un código postal no se mapea a exactamente una ciudad en todos lados: algunos cubren un grupo de áreas de reparto en varios municipios. La invariante no es un código para una ciudad, sino un código para un conjunto pequeño y estable de ciudades, así que una prueba que exija unicidad estricta falla contra datos de referencia reales.

Nombra el resultado esperado en cada fixture y mantén los casos negativos en la misma suite que los positivos: una suite de desajustes con solo tuplas válidas esconde el caso interesante. La mecánica de armar y versionar esos conjuntos está en datos de dirección en fixtures de prueba.

¿Por qué una dirección con formato válido puede seguir estando mal?

Porque el formato es una condición necesaria y muy lejos de ser suficiente. Una cadena puede cumplir el patrón de un país y no existir, o existir y pertenecer a otra región. La comprobación de patrón solo responde a la pregunta de si el valor podría ser un código postal; no responde a si ese código postal es el de esa ciudad.

Hay además una segunda razón, más estructural: la validación del formulario revisa un campo a la vez, mientras que los sistemas posteriores revisan relaciones. Una transportadora, un motor de impuestos y un servicio de limpieza de direcciones cruzan ciudad, región y código postal, así que rechazan combinaciones que una expresión regular por campo acepta sin problema. Cuando el usuario ya cerró la compra, ese rechazo llega como una incidencia de soporte y no como un error de validación.

Y hay una tercera, que es la peor: el campo guardado puede no ser el campo ingresado. Si una transformación silenciosa recorta un cero inicial, pasa todo a mayúsculas o recorta espacios internos, el registro que se guarda es distinto del que la persona escribió, y ninguna de las dos versiones es necesariamente incoherente consigo misma. La incoherencia aparece al mezclar una mitad normalizada con otra que no lo está. La convención de escritura de cada país, incluidas las diferencias de orden entre sistemas latinos y de Asia Oriental, está descrita en formato de dirección internacional.

Tres defectos de formulario que una dirección falsa expone más rápido

Los registros generados no sirven solo para comprobar que un formulario los acepta. Como un generador produce valores en los límites del formato de un país —nombres de calle largos, códigos postales de ocho caracteres, letras donde una regla ingenua espera dígitos—, encuentra rápido estos tres defectos.

Truncamiento a una longitud fija. Una columna o un campo dimensionado para el valor realista más corto corta en silencio uno más largo. El código postal británico es el ejemplo clásico, pero una dirección de dos líneas con un nombre de división largo hace lo mismo, y un código postal truncado se guarda sin queja alguna.

Obligatoriedad que no sigue al país. Marcar ciudad, región o código postal como obligatorio para todos los países contradice a los países que no tienen ese campo o que no lo usan en el direccionamiento postal. El formulario no está mal para el país para el que se escribió; está mal para el segundo país al que se extendió tres meses después.

Normalización silenciosa que cambia el valor guardado. Convertir a mayúsculas un código sensible a mayúsculas, recortar espacios internos o hacer pasar la entrada por un tipo numérico reescribe lo que la persona escribió. El usuario ve un formulario en verde y el registro guarda otra cosa, que es la clase más difícil de notar porque nada falla de forma visible.

Cuando el frontend y el backend no coinciden

La validación de direcciones suele existir dos veces: un patrón en el navegador para dar respuesta rápida y una regla en el servidor porque no se puede confiar en el navegador. Las dos se desincronizan, y esa deriva produce el peor estado de error: un formulario que dice que todo está bien y una petición que vuelve rechazada.

  • El mismo valor validado en etapas distintas. El navegador revisa la cadena que la persona escribió, con espacios y guiones incluidos; el servidor revisa un valor que el código consumidor ya normalizó, o al revés. Ambos son correctos en aislamiento y se contradicen en cualquier entrada cuyas dos representaciones difieran.
  • Conjuntos de reglas distintos. El navegador conoce un patrón por país; el servidor conoce un patrón, una longitud y una verificación de relación. El usuario no ve ningún error y recibe un rechazo genérico.
  • Tipos distintos. El navegador envía una cadena vacía donde el servidor espera nulo, o una cadena donde el servidor espera un número. Entonces decide la columna: un cero inicial desaparece, o una cadena vacía falla una restricción de unicidad que los nulos sí habrían satisfecho.

La forma de mantenerlos alineados es un corpus compartido y una única fuente de verdad. Toma los registros generados que ya produces, pasa la misma lista al validador del navegador en una prueba unitaria y al validador del servidor a través de su API, y asegura que ambos devuelvan el mismo veredicto para cada registro. Todo lo que no coincida es deriva que encontraste antes que un usuario.

¿Cómo se evita el desajuste al generar los datos?

La primera decisión es generar la tupla y no los campos. La unidad de generación debería ser un registro de dirección que ya contenga un país, una división de primer nivel, una ciudad y un código postal coherentes entre sí. El generador elige un lugar, no tres cadenas que por casualidad terminaron una al lado de la otra. Puedes ver el resultado en el generador de direcciones, donde el país, la división, la ciudad y el código postal salen de un único registro de datos.

La segunda es validar después de generar, no en lugar de generar. Ejecuta la misma herramienta de validación que publicas en producción sobre las filas generadas, en lote. Si el validador es lo que rechaza una fila, encontraste el desajuste antes que una prueba y además probaste el validador contra un corpus grande y variado, algo difícil de conseguir con muestras escritas a mano. Para ver cómo se comportan los datos de referencia de un país concreto, la ficha de Estados Unidos y la de México muestran qué campos entran en un registro completo.

La tercera es tratar el teléfono como parte de la dirección. Guarda el formato internacional, muestra el formato nacional y deriva el formato nacional del mismo registro de país que usaste para la dirección. Un número y un país elegidos de forma independiente terminarán contradiciéndose.

La cuarta es mantener los casos negativos a propósito. Una suite de pruebas necesita filas que deban fallar: un código postal estadounidense pegado a una ciudad británica, un teléfono con el prefijo de troncal todavía puesto, un país sin códigos postales que igual lleva uno. Genera un conjunto limpio para el camino feliz y escribe a mano un conjunto sucio pequeño para el camino de fallo.

¿Cómo se fija un informe de error sin copiar datos reales?

Un informe de error sobre datos de dirección solo sirve si la siguiente persona puede reconstruir el registro exacto: la entrada exacta, el país, el entorno y el resultado esperado. Una captura de pantalla rara vez lleva la entrada, porque el formulario muestra el valor después de que el navegador lo formateó.

La solución es fijar el registro por clave en lugar de por copia. Un generador con clave devuelve el mismo registro para la misma clave, así que el informe puede llevar unos pocos caracteres en vez de una fila completa, y cualquiera puede pegarlos en el generador de direcciones para obtener la misma persona, calle, ciudad y código postal. Los campos mínimos de un informe útil son estos.

Campo del informe Qué debe contener
Fixture El tipo de registro, la clave y el país
Ingresado El valor tal como lo escribió la persona
Guardado El valor tal como quedó en la base o en la respuesta
Esperado El comportamiento correcto, en una frase
Obtenido El error literal, con el estado y el mensaje
Entorno Dónde se reprodujo y sobre qué revisión
Repetición Una segunda clave que muestre el mismo síntoma

Incluye siempre el valor guardado además del ingresado. La diferencia entre ambos suele ser el defecto, y es invisible en una captura del formulario. Nunca adjuntes la dirección, el teléfono o el número de identidad de una persona real para que un informe parezca realista: la clave fijada te da un registro realista que cualquiera puede regenerar sin exponer datos de nadie.

Siguientes pasos

Elige tres países con convenciones bien distintas —por ejemplo Estados Unidos, Alemania y México— y arma para cada uno un conjunto pequeño con un registro válido, un registro con el código postal de otra región y un registro de un país sin código postal. Ejecuta las invariantes de tupla de esta guía sobre los datos de prueba que ya tienes y anota cuáles fallan; esas son las filas que están mintiendo hoy.

Los ejemplos que produce el generador son ficticios y su único uso previsto es la prueba de software: no describen una vivienda, una persona ni un domicilio real, y no sirven para enviar correspondencia ni para acreditar residencia ante nadie. Úsalos como entrada reproducible de tus pruebas y no como sustituto de una dirección real en ningún flujo de producción.

Seguir leyendo

Artículos sobre Generador de direcciones falsas