El genio y el contrato

Cómo encajan realmente el desarrollo guiado por especificaciones (SDD) y el desarrollo guiado por pruebas (TDD) cuando un agente no determinista escribe tu código, y dónde la versión ingenua se desmorona silenciosamente.

Un genio impredecible

Kent Beck lleva cinco décadas defendiendo que las pruebas deben ser lo primero. Por lo tanto, vale la pena observar cómo describe los agentes de codificación de IA con los que trabaja actualmente: un “genio impredecible” que concede tus deseos, a menudo de maneras literales e inesperadas. Pides algo. Te lo da. algoQue eso sea realmente lo que necesitabas es otra cuestión.

En la misma conversación, Beck llama TDD a un "superpotencia" con estos agentes, porque introduce regresiones constantemente y un conjunto de pruebas es la forma más económica de detectarlas. Pero también deja escapar un detalle que debería hacerte reflexionar: tiene problemas para detener a los agentes de eliminando las pruebas para que aprueben. Las pruebas como defensa y a la vez como objeto de manipulación: ese es el problema.

Una breve aclaración sobre los términos, ya que uno de estos acrónimos se usa de forma imprecisa. TDD es la disciplina más antigua: escribir primero una prueba que falle, escribir el código justo para que pase, ordenar y repetir. SDD es la más nueva: capturar lo que se está construyendo como una especificación técnica estructurada (las formas de la API, los modelos de datos y los criterios de aceptación) y tratar ese documento como el contrato que el código debe cumplir. Lo importante es que SDD es una , no un producto. Kit de especificaciones de GitHub es una herramienta que facilita su adopción, y es el ejemplo que se utiliza a lo largo de todo el texto, pero todo lo que se dice aquí se aplica a cualquier configuración de SDD. (Tampoco es lo mismo que impulsado por la historia desarrollo, que funciona a un nivel más flexible de historias de usuario y se relaciona de manera diferente con TDD.)

¿Por qué ninguno sobrevive solo al genio?

Si se ejecuta SDD por sí solo, el significado se desvía: el agente forma su propia interpretación de una especificación ambigua y construye algo internamente consistente que aún no capta lo que se quería decir, porque la prosa no se puede ejecutar y nada hace que el código vuelva a las palabras. Si se ejecuta TDD por sí solo, se obtiene lo contrario: código que pasa las pruebas que tiene delante y nada más, sin una especificación que diga qué son esas pruebas. debo afirman, por lo que terminan codificando lo que el agente decidió construir. En cualquier caso: marcas de verificación verdes, objetivo equivocado.

La razón para combinarlos no es que ambos sean buenos. Es que La especificación y la prueba son dos codificaciones independientes de la misma intención. —uno legible para humanos, otro ejecutable por máquina— y cada uno cubre las deficiencias del otro. La especificación justifica la existencia de la prueba, de modo que el conjunto de pruebas no sea simplemente un reflejo del código. La prueba da fuerza a la especificación, impidiendo que el agente pueda reinterpretarla discretamente.

Un panel de especificaciones a la izquierda y un panel de prueba a la derecha apuntan hacia adentro, hacia un agente central, enmarcándolo desde dos lados.

Una columna vertebral, dos compuertas, un borde de retroalimentación.

El diagrama a continuación muestra la forma. Una persona define la intención; Spec Kit's specify y plan Los comandos lo convierten en una especificación y un plan; una persona los revisa, como un punto de control, no como un bloqueo permanente. Tres detalles determinan si esto funciona en la práctica.

en primer lugar, analyze se ejecuta antes que cualquier código. Es una comprobación de coherencia de solo lectura en especificaciones, planes y tareas. El instinto es dejarla para el final, pero Spec Kit... Inicio rápido propio es explícito que el primer pase pertenece antes implementMientras tanto, corregir las brechas sigue siendo económico. Si lo desea, puede volver a ejecutarlo después como una revisión de deriva, pero la pasada de carga es la que se realiza antes de que el agente escriba una línea.

En segundo lugar, Una persona es propietaria de la prueba de aceptación. — la siguiente sección explica lo que eso significa. En tercer lugar, el agente incorpora cortes verticalesSe trata de un pequeño fragmento de comportamiento llevado de principio a fin: una única prueba fallida, el código justo para superarla, una limpieza y luego la siguiente parte, en lugar de generar todo el conjunto de pruebas de antemano o emitir cientos de líneas a la vez, que es lo que produce un código que parece plausible pero que falla de maneras imposibles de localizar. Además, el código se fusiona solo cuando las pruebas son correctas, se ha comprobado que el conjunto de pruebas detecta errores y las pruebas confirmadas no se han modificado para forzar el resultado.

Un proceso vertical que va desde la intención humana hasta una puerta de fusión, con el análisis como puerta previa al código, una prueba de aceptación de solo lectura gestionada por humanos, un bucle de código de segmento vertical y una arista de retroalimentación desde el bucle de vuelta a la especificación.

¿Quién vigila las barandillas?

Es fácil imaginar esto como un flujo ordenado “especificación → prueba → código” y dejarlo ahí. La verdadera ingeniería está en los modos de falla, y todos se reducen a una pregunta: si el agente escribe la especificación, escribe las pruebas, y quien escribe el código, ¿qué es lo que realmente comprueba?

¿Quién decide qué significa “correcto”?

Si un modelo escribe los tres —la especificación, las pruebas y el código— todos comparten el mismo punto ciego. Una sola interpretación errónea de la intención da como resultado una especificación que codifica la interpretación errónea, pruebas que la imponen y código que las supera. Todo está en verde; todo está mal. Las dos codificaciones “independientes” solo permanecen independientes si Una persona posee al menos uno de ellos, algo que el agente no puede reescribir discretamente.

El mejor artefacto para encomendar a una persona es la prueba de aceptación: la prueba que indica que "esta función está terminada y se comporta correctamente". Una especificación escrita en prosa puede respetarse al pie de la letra y aun así infringir su espíritu; una prueba es una afirmación concreta, de aprobación o reprobación. Ser propietario de algo no significa que una persona escriba a mano cada afirmación; el agente puede redactar las pruebas. Significa que una persona las revisa, aprueba lo que afirman y se hace responsable de ellas. antes de que se conviertan en la barra contra la que se mide el código, en lugar de dejar que el mismo agente genere y fusione silenciosamente el suyo propio. En términos de pruebas, la prueba de aceptación es su oráculo: lo que decide si el código es correcto. Como han descubierto otros que trabajan en esto, Las pruebas controladas por humanos son la última línea de defensa. — porque bajo presión, el instinto del agente es eliminar una prueba fallida en lugar de corregir el código. Si el agente puede editar el oráculo, entonces no hay oráculo.

El verde es un proxy, y los proxies se manipulan.

La frase «El agente no puede avanzar hasta que la prueba pase» suena a garantía. Pero no lo es. Hay muchas maneras de lograr que una prueba pase sin cumplir realmente su propósito: debilitar lo que verifica, omitirlo, reemplazar el componente real con un stub, codificar directamente la respuesta esperada, ignorar el error o, simplemente, reescribir la prueba. El problema es el clásico: en el momento en que «lograr que las pruebas pasen» se convierte en el objetivo, el éxito de las pruebas deja de ser una señal fiable de que algo funciona.

Esto no es hipotético. Aider, un popular agente de codificación de línea de comandos y una opción razonable para el ciclo de compilación, lo hará por diseño. edita las pruebas que decide que están mal En lugar de forzar el código para que se ajuste a ellos. Eso es realmente útil cuando una persona está conduciendo; es un fallo cuando el agente se ejecuta por su cuenta. Entonces, ¿cómo se evita que el agente manipule la puerta? Dos medidas de seguridad hacen la mayor parte del trabajo, y un simple recuento de aprobados/reprobados no es ninguna de ellas.

Lo que las pruebas no pueden decir

Las pruebas unitarias responden a una pregunta específica: ¿esta función hace lo que dije, de forma aislada? No dicen nada sobre el rendimiento, la seguridad, la accesibilidad o, lo que es más importante, si la te En realidad funciona para un usuario real. Esa última brecha es precisamente donde falla el código generado por IA: el agente detecta una unidad aislada y silenciosamente rompe el recorrido de extremo a extremo que la atraviesa. Así que trate Pruebas de extremo a extremo y de integración como un nivel de primera clase, no como algo secundario. — la capa que controla la aplicación real como lo haría un usuario y detecta lo que las pruebas unitarias no pueden ver. Herramientas como Dramaturgo MCP Incluso permite que el agente ejecute un navegador real y verifique su propio trabajo comparándolo con ese recorrido, en lugar de adivinar. Para los requisitos que no se pueden probar, conviértalos en una puerta de enlace explícita en su canalización de compilación: una esperanza no es un control.

La refactorización no es opcional.

El ciclo de TDD tiene tres pasos, no dos: escribir una prueba que falle (rojo), hacer que pase (verde) y luego limpiar el código recién escrito (refactorizar). Si se deja solo, el agente tiende a omitir el tercer paso y lanzar el código en cuanto la prueba pasa (verde). Pero la refactorización es fundamental para mantener la calidad del código, y omitirla con un agente rápido e incansable es precisamente lo que genera el desorden que todo el proceso pretende evitar. Mantén la refactorización en el ciclo y observa una señal de complejidad o de cambios en el código para detectar la parte que el agente sobredimensionó.

La especificación está en constante evolución, no congelada.

Existe una tensión real entre los dos métodos. SDD quiere que la especificación esté definida antes de escribir el código; ese es el objetivo principal de tener un contrato. TDD, por el contrario, es en parte una forma de descubrir El diseño: a menudo uno se da cuenta de que un requisito era erróneo, o que una interfaz era incómoda, precisamente al escribir la prueba correspondiente. Entonces, ¿qué sucede la primera vez que una prueba revela que la especificación en sí estaba incompleta?

La solución es tratar la especificación como un documento vivo, no como una aprobación única. Cuando cambia un requisito —o una prueba revela una deficiencia— no se modifica la prueba para que coincida con el código; primero se actualiza la especificación (un cambio pequeño y revisado), se actualizan las pruebas para que coincidan, se observan sus fallos y se deja que el agente las haga pasar. Es el mismo ciclo rojo-verde, aplicado tanto a la especificación como al código, y conlleva una regla que no se debe romper: Los cambios de flujo especifican → prueba → código, nunca prueba → código por sí solos. Si se mantiene esa postura, los cambios en los requisitos dejarán de ser el aspecto que peor maneja este enfoque y se convertirán en el aspecto que mejor maneja.

La puerta vive en el entorno

La elección de diseño clave es donde se desarrolla la disciplinaEs tentador convertirlo en una propiedad de una herramienta específica: una planifica, otra programa. No lo hagas. Sitúe el control en el entorno (su control de versiones y su integración continua) en lugar de en un único agente. Una vez instalado allí, el agente de codificación se convierte en una pieza intercambiable en lugar de algo en lo que confías.

Tu herramienta SDD controla la estructura básica de la planificación. Con Spec Kit eso es constitution → specify → clarify → plan → tasks → analyze → implement. Pon las reglas TDD en su archivo constitucionalEscribe una prueba fallida antes de la implementación; nunca marques una tarea como completada si las pruebas fallan; nunca modifiques una prueba confirmada solo para que pase. Cada comando hereda estas reglas, por lo que no dependes de que el agente las recuerde durante una sesión larga.

La puerta de enlace es un gancho previo a la confirmación y una comprobación de CI, no una solicitud. Las pruebas pasan, las mutaciones son detectadas, las pruebas confirmadas permanecen intactas, impuestas por el entorno, por lo que se mantiene independientemente de si el código proviene de Spec Kit. implement, de Aider, o cualquier otra cosa.

El ejecutor es conectable. El lugar de nacimiento de Aider --auto-test El bucle proporciona un ciclo por cambio más ajustado que un comando por lotes y enruta los modelos según su coste: un modelo robusto para especificaciones y planes, y uno más económico para el bucle de alta frecuencia, con almacenamiento en caché. Úselo o no. La metodología es la clave.

Adapta la ceremonia al riesgo

Un proceso que no se puede escalar se abandona. Una ceremonia completa (una constitución del proyecto, una especificación, un plan, un desglose de tareas, más pruebas de mutación) es excesiva para una corrección de errores de una sola línea. Así que ejecute dos carriles, una división que Documentación propia de Spec Kit recomienda.

El carril rápido, para trabajos de bajo impacto: una intención de una sola línea, una o dos pruebas revisadas por humanos, implementación contra la puerta. El carril completo, para subsistemas nuevos o superficies reguladas: toda la estructura más pruebas de mutación y una capa de integración. La ceremonia se convierte en una función del riesgo en lugar de un impuesto fijo, que es la respuesta honesta a «esto parece una cascada con pasos adicionales».

¿Merece la pena el gasto adicional?

Nada de esto es gratis. Estás pagando por más llamadas al modelo, más ejecuciones de pruebas y más idas y venidas que si simplemente dejaras que un agente escribiera el código de una sola vez, así que es justo preguntarse si el coste adicional se justifica. La forma de mantener la cordura es invertir donde importa: un modelo robusto para la especificación y el plan, uno más económico y rápido para el ciclo de compilación de alta frecuencia; ejecutar las comprobaciones costosas, como las pruebas de mutación, solo en la fusión, no en cada iteración; y mantener los segmentos pequeños para que cada ciclo siga siendo económico. Pero la verdadera pregunta es con qué lo estás comparando. La base no es un ingeniero sénior escribiendo código impecable, sino un agente sin supervisión que entrega código plausible pero defectuoso que luego tienes que depurar durante horas. En comparación, la sobrecarga es lo que te da un resultado en el que realmente puedes confiar.

Cuándo no hacer esto

Y a veces la respuesta es que no vale la pena en absoluto. Sáltate todo el proceso para prototipos desechables y pruebas rápidas, donde el objetivo es aprender rápido y descartar. Sáltatelo para cambios realmente triviales, donde configurar la puerta cuesta más que el error. Y sé honesto sobre los dominios donde no puedes escribir una prueba significativa de forma económica: allí el oráculo es vacío y las garantías son teatro. Den Delimarsky observa Tras la experiencia práctica con el kit de especificaciones, queda claro que las especificaciones no son la panacea. Mencionar estas limitaciones no es una simple evasiva, sino lo que distingue una metodología de un argumento de venta.

El listón acaba de subir.

Lo que sobrevive a la automatización no es escribir código. Es saber qué es lo correcto, expresarlo con la precisión suficiente para que ni siquiera un genio literal pueda malinterpretarlo, y ser capaz de determinar si se ha logrado. SDD es cómo se expresa. TDD es cómo se verifica.

El agente eliminará alegremente tus pruebas para que desaparezca el rojo. Así que la especificación, el conjunto y el juicio detrás de ambos no son una ceremonia alrededor del trabajo real. Con un agente involucrado, son El verdadero trabajo.

Fuentes y herramientas

  1. Kent Beck habla sobre TDD, agentes de IA y el “genio impredecible” — El ingeniero pragmático
  2. Por qué las pruebas controladas por humanos son la última línea de defensa — AllStacks
  3. Kit de especificaciones de GitHub — repo · Inicio rápido · constitución y los nueve artículos
  4. Desarrollo basado en especificaciones con Spec Kit — Microsoft para desarrolladores · La inmersión profunda de Den Delimarsky
  5. Bucle de prueba de Aider — Análisis y pruebas · referencia de opciones
  6. Cerrando el ciclo de verificación del agente — Dramaturgo MCP

También puede interesarle