Blog ·
Un script de conversión que abarcó demasiado
Un script de tipografía curvó un apóstrofo en una cita de salida de programa, en un artículo que nunca debió tocar. Las comprobaciones siguieron verdes.
Por Provibr
El francés y el italiano exigen un apóstrofo tipográfico en lugar de uno recto, y hay una prueba que lo impone. Escribir ese carácter directamente en un fichero fuente no es fiable: según cómo se produzca el fichero, un intérprete de comandos, un heredoc o una herramienta de edición pueden aplanarlo de vuelta. Así que escribimos el carácter recto y ejecutamos después un pequeño script que lo convierte.
Ese script enmascara el código. Todo lo que va entre comillas invertidas y todo lo que va dentro de un bloque delimitado se deja en paz, porque un apóstrofo dentro de un fragmento de código cambiaría el fragmento, y la comparación de hechos se pondría en rojo con toda la razón.
Se ejecutó con un comodín sobre toda una carpeta de idioma. Convirtió un apóstrofo dentro de una cita de salida de programa, en un artículo escrito por otra ronda, que estaba en esa misma carpeta.
El enmascarado era correcto y el objetivo estaba equivocado
La línea que dañó era una cita de lo que había impreso un comando, puesta entre comillas angulares como prosa corriente y no marcada como código. Algo con la forma de Locking administration user's password. Ese apóstrofo pertenece a la máquina que lo emitió, y curvarlo hace que el artículo afirme que la máquina dijo algo que no dijo.
La regla de enmascarado es correcta. Las comillas invertidas y los bloques delimitados son código. Una cita de salida de programa compuesta como prosa no está marcada como código y no se puede distinguir de la prosa mirando los caracteres, porque eso es precisamente lo que es: prosa que cita a una máquina.
Así que el defecto no está en el enmascarado. Está en la selección. Tres artículos de otras rondas fueron modificados por un script escrito para tocar cuatro.
Por qué la comprobación de construcción no lo notó
Esta es la parte que se generaliza más allá de un script.
Nuestros artículos son generados. La fuente es markdown, la salida son ficheros generados que se guardan en el repositorio, y hay una comprobación que reconstruye desde la fuente y exige que el resultado sea idéntico byte a byte a lo guardado. Si divergen, se pone en rojo.
No divergieron. El script cambió la fuente, se ejecutó la construcción, la salida se regeneró a partir de la fuente cambiada, y las dos coincidieron a la perfección. La comprobación responde a «¿es la salida coherente con la fuente?», que es una pregunta real y no es esta. Nada en la cadena de construcción responde a «¿ha cambiado esta ronda solo lo que debía cambiar?».
La prueba de tipografía tampoco, por el mismo motivo a la inversa: un apóstrofo curvo en francés es el carácter correcto. El cambio hizo el fichero más conforme, no menos.
Lo único que lo mostró fue git status sobre rutas fuera de los ficheros propios de la ronda. Esa es ahora la regla: después de ejecutar cualquier transformación, listar los ficheros cambiados y confirmar que todos son propios.
La regla que se sigue de ahí
Ejecute un script de transformación sobre los nombres de fichero de su propia ronda. Nunca sobre un comodín que abarque un directorio.
Eso suena obvio puesto por escrito, y no era obvio mientras se escribía, porque un comodín sobre una carpeta de idioma es la manera natural de expresar «convertir los artículos franceses» y el script tenía una propiedad de seguridad correcta que lo hacía parecer seguro: exige al menos una sustitución por fichero, de modo que una ejecución que en silencio no hace nada no pueda informar de éxito. Esa comprobación va sobre el éxito vacío. No dice nada sobre el alcance.
Una comprobación de seguridad que protege contra hacer demasiado poco no es una comprobación de seguridad contra hacer demasiado. Son propiedades separadas y necesitan mecanismos separados.
Dos versiones más pequeñas del mismo problema
La ronda que se topó con esto se topó también con dos fallos de traducción que vienen de la misma familia: algo que debería haber sido inmune a la edición no estaba marcado como tal.
Una directiva de caché aparecía en la fuente como prosa desnuda en lugar de entre comillas invertidas. Dos idiomas la tradujeron, lo que convierte una palabra clave en una frase, y uno de ellos además convirtió una duración de un año en un plural. La comparación de hechos no atrapa ninguna de las dos cosas, porque esa comparación cubre lo que va entre comillas invertidas y lo que es un dígito, y una palabra clave desnuda no es ninguna de las dos. La reparación es marcarla como elemento literal en los nueve idiomas, tras lo cual la comparación la cubre de forma permanente.
El segundo era una tabla de etiquetas de interfaz. El artículo inglés la usaba para mostrar que dos listas de nombres se habían separado, y declaraba explícitamente que la separación se había medido en inglés. Seis de las ocho traducciones tradujeron la tabla. Un par de nombres traducido no es una versión más suave de la medición; es una medición distinta, que nunca se tomó. Deshacer eso costó 26 sustituciones.
Los dos fallos tienen la misma forma que el apóstrofo: un trozo de texto que es dato y no lenguaje, situado en una posición donde nada lo marca como dato.
Lo que responde una comprobación es más estrecho que lo que parece responder
Los tres mecanismos en juego aquí son correctos, y cada uno respondía a una pregunta contigua a la que importaba.
| Comprobación | La pregunta que responde | La que no responde |
|---|---|---|
| La comprobación de construcción de contenido | ¿es la salida generada coherente con la fuente? | ¿tocó este cambio solo los ficheros previstos? |
| La prueba de tipografía | ¿usa este fichero los caracteres correctos para su idioma? | ¿están esos caracteres en los sitios correctos? |
| La guarda del propio script | ¿recibió este fichero al menos una sustitución? | ¿recibió algún fichero una sustitución que no debía? |
Ninguno de ellos está mal diseñado. El fallo es la suposición de que un muro de comprobaciones verdes constituye cobertura, cuando lo que constituye en realidad es cobertura de las cosas en las que alguien pensó.
La respuesta más barata a eso no es otra comprobación. Es mirar la diferencia, al nivel de los nombres de fichero, antes de guardar nada que haya producido un script.
Lo que dejaríamos por escrito
- Acote una transformación a los ficheros de su propia ronda. Un comodín sobre un directorio no es un alcance, es una categoría.
- Una guarda contra hacer demasiado poco no dice nada sobre hacer demasiado. Son propiedades distintas.
- Una cita de salida de programa es un dato. Márquela como código, o una transformación de texto la tratará como lenguaje.
- Una comprobación de coherencia entre fuente y salida es ciega a un cambio en las dos. Responde sobre concordancia, no sobre intención.
- Un cambio que hace un fichero más correcto es el más difícil de notar, porque todas las señales de calidad van en la dirección buena.
- Lea la lista de ficheros de su propia diferencia. Es la única comprobación que responde a la pregunta del alcance.
- Todo lo que sea una palabra clave va entre comillas invertidas en la fuente, en todos los idiomas, o alguien lo traducirá y a ninguna prueba le importará.
- Una medición traducida es una medición inventada. Si el sentido de una tabla es que dos cosas difieren, la tabla es evidencia y no prosa.
Para que quede claro qué es esto: el daño se revirtió, la ronda terminó con la comprobación de contenido en 815 de 815 ficheros generados idénticos byte a byte, el conjunto de pruebas web en 4546 en verde, los conjuntos de paquetes, pasarela y herramientas en 7236 en verde, la comparación de hechos sobre 1240 párrafos sin ningún hallazgo, los enlaces en 81 de 81, las tablas en 99 de 99 y el barrido de disposición en 108 de 108 a 390 píxeles contra una construcción de producción. La prueba de tipografía se demostró en rojo con dos defectos plantados y en verde después. Sin demostrar: hay un lector por traducción, tres idiomas se comprobaron solo en disposición, tipografía y estado HTTP, y las cifras citadas de rondas anteriores no se volvieron a medir aquí.
Del trabajo de plataforma en Provibr. Lo que encontró un segundo lector en esos mismos ocho artículos está en tres fallos que ningún script podía ver, y lo que nueve catálogos le hacen a un conjunto fijo de controles está en dieciséis mil claves, nueve idiomas.