< BACK Por Qué Volví a Escribir Tests (La IA Me Obligó) -- ilustración de arte lineal

Por qué volví a escribir pruebas (la IA me obligó)

A principios de 2022, tomé una decisión silenciosa: dejé de escribir pruebas unitarias para la mayoría de los proyectos de WordPress y Node que pasaban por Seahawk. Sin anunciarlo. Sin post en el blog al respecto. Simplemente... dejé de hacerlo. La justificación era sólida, pensé, estábamos lanzando 15 a 20 sitios de clientes al mes, tenía otros tres desarrolladores en rotación, y las pruebas que escribía se sentían como documentación que nadie leía. El QA manual atrapaba los bugs reales. Las pruebas eran teatro.

Avancemos a finales de 2023. GitHub Copilot había estado en mi editor durante unos ocho meses. También había empezado a usar Cursor a un lado para cualquier cosa greenfield. La velocidad era genuinamente notable. Pero algo comenzó a pasar. Bugs aparecían en lugares que no había tocado. Lógica que se veía correcta estaba mal en casos límite que nunca se me había ocurrido verificar. Y lo peor, la IA no tenía idea de que estaba mal. Escribió el código roto con la misma indentación confiada que siempre usa.

Fue entonces cuando retomé las pruebas.

---

El período en que dejé de probar (y por qué tenía sentido en ese momento)

¿Respuesta honesta? Para cierto tipo de proyecto, saltarse las pruebas fue la decisión correcta. Si estás construyendo un sitio de folleto de cinco páginas en WordPress, escribir pruebas PHPUnit para un plugin de formulario de contacto es teatro. Me mantengo en eso.

El pan de cada día de Seahawk durante mucho tiempo fue exactamente ese trabajo: alto volumen, complejidad relativamente baja, alcance bien definido. Un cliente te pasa un archivo de Figma, lo construyes, lo verificas con QA, lo lanzas. Los ciclos de retroalimentación eran cortos. Si algo se rompía, lo sabías en cuestión de horas. Escribir pruebas para ese contexto es el equivalente del desarrollador a plastificar una nota Post-it.

Pero generalicé esa lección demasiado agresivamente. Comencé a tratar todos los proyectos como sitios de folletos. Incluso los que tenían flujos de pago de WooCommerce personalizados. Incluso el dashboard fintech que construimos a principios de 2023 para un cliente en Frankfurt, REST API completamente personalizada, autenticación JWT, tres niveles diferentes de permisos de usuario. Sin pruebas. Solo "QA manual cuidadoso". Eso fue arrogante, y nos pasó factura.

El proyecto de Frankfurt se lanzó con un bug de permisos que permitía a usuarios de nivel editor consultar datos de nivel administrador bajo una combinación específica de filtros. No lo detectamos hasta que su equipo interno ejecutó una revisión de seguridad seis semanas después del lanzamiento. Vergonzoso. Corregible. Pero el tipo de cosa que una prueba de integración básica habría señalado antes de que siquiera levantáramos un pull request.

---

Qué herramientas de codificación con IA realmente cambiaron

Aquí está lo que la mayoría de la gente se pierde cuando habla de Copilot o Cursor o sea cual sea el modelo que esté de moda este mes: el código se ve bien. Ese es el problema.

Cuando un desarrollador junior escribe código defectuoso, a menudo puedes ver la incertidumbre en él. Nombres de variables raros, un comentario que dice // no estoy seguro de esto, una función que claramente fue copiada y pegada dos veces. El código delata su propia fragilidad. El código de IA no. Es consistente en estilo, bien nombrado, y estructurado de una manera que se lee como intencional. La confianza es completamente cosmética.

Estudios del grupo de Interacción Humano-Computadora de Stanford han señalado que los desarrolladores que usan asistentes de IA tienden a sobre-confiar en el código generado en la primera lectura. Eso concuerda con mi propia experiencia. Echaría un vistazo a una función de 40 líneas que Copilot había escrito, pensaría "sí, es básicamente lo que yo habría escrito", y seguía adelante. A veces estaba bien. A veces había entendido silenciosamente mal lo que realmente necesitaba.

El modo de fallo específico que seguía encontrando: lógica condicional alrededor de casos extremos que la IA no tenía razón para anticipar. Escribía una función que manejaba el camino feliz perfectamente y luego fallaba silenciosamente en entradas nulas, arrays vacíos, o formatos de fecha no estándar. Cosas que me habrían tomado treinta segundos pensar si hubiera escrito el código yo mismo, porque habría estado pensando mientras escribía.

La Trampa de la Velocidad

Hay una trampa de productividad real aquí. La IA te hace rápido. La rapidez se siente como calidad. Empiezas a enviar más rápido y empiezas a revisar menos cuidadosamente porque la velocidad se siente como evidencia de calidad. No lo es. La velocidad y la corrección no están correlacionadas cuando estás usando un modelo de lenguaje.

Puse aproximadamente 40% más características en un proyecto de cliente el septiembre pasado de lo que hubiera logrado sin asistencia de IA. El proyecto también tuvo más bugs post-lanzamiento que cualquier cosa que hubiera enviado en dos años. No fueron bugs catastróficos. Pero sí molestos. El tipo que erosiona la confianza del cliente.

---

Por Qué Las Pruebas Funcionan Diferente Ahora (Con IA en el Ciclo)

Cuando volví a las pruebas, no volví al flujo de trabajo anterior. Escribir pruebas primero, luego la implementación, luego revisión de código asistida por IA, ese es el ciclo en el que me he instalado ahora.

Lo interesante es que la IA es realmente excelente escribiendo pruebas, de una manera que no siempre lo es escribiendo lógica de aplicación. Dale a Copilot una firma de función bien definida y pídele que genere una suite de pruebas y producirá cobertura de casos límite que me hubiera tomado veinte minutos escribir manualmente. Imagina bien los caminos infelices cuando la tarea es específicamente "encontrar formas en que esto puede romperse".

Así que he invertido la cosa de cierta forma. Escribo la especificación de prueba. La IA completa los casos de prueba. Luego la IA escribe la implementación. Luego leo la implementación a través del lente de esas pruebas, en lugar de solo leer el código a frio.

Es más lento que la programación pura por intuición. Pero es más rápido que el flujo de trabajo antiguo de escribirlo todo manualmente incluyendo pruebas. Y no ha enviado cero bugs de permisos desde Frankfurt.

Las Herramientas Que Realmente Estoy Usando

  • [Vitest](https://vitest.dev) para cualquier cosa JavaScript o TypeScript. Reemplazó Jest completamente para mí el año pasado, la configuración es más sensata y el modo watch es rápido.
  • PHPUnit aún, para WordPress y trabajo PHP personalizado. Nada lo ha reemplazado.
  • El atajo "test this function" de Cursor, genuinamente una de las características individuales más útiles en cualquier editor que haya usado.
  • GitHub Actions para CI. Las pruebas se ejecutan en cada push a main. Toma alrededor de 90 segundos en la mayoría de proyectos.

---

El Argumento Contra las Pruebas (Presentado de Forma Justa)

Quiero darle a esta posición una consideración justa porque la sostuve durante casi dos años.

El argumento real no es "las pruebas son inútiles". Es "las pruebas tienen un costo y muchos proyectos no justifican ese costo". Escribir y mantener un suite de pruebas requiere tiempo. En un proyecto con una vida útil corta, un micrositio de campaña, una página de destino de marketing, un prototipo de hackathon, esa inversión de tiempo tiene cero retorno. El proyecto estará muerto antes de que las pruebas te ahorren algo.

Y hay un punto más sutil: las malas pruebas son peor que ninguna prueba. Un conjunto de pruebas que pasa porque las pruebas son tautológicas (esencialmente estás verificando que tu función devuelva lo que le dijiste que devuelva) te da una confianza falsa. He visto esto en agencias. Desarrolladores escribiendo pruebas que siempre pasan porque nadie cuestionó lo que realmente estaban verificando.

Martin Fowler ha escrito bien sobre esto: los porcentajes de cobertura no son una medida de la calidad de las pruebas. Un número de cobertura del 90% puede enmascarar un suite completamente hueca.

Entonces: no pruebes todo. No pruebes porque se sienta profesional. Prueba porque identificaste lógica crítica que sería costoso romper.

---

Qué Pruebo Ahora (Y Qué No)

Esta es la decisión real a la que llegué después de los últimos ocho o nueve meses:

Pruebo:

  1. Cualquier función que maneje dinero, permisos o transformación de datos
  2. Cualquier endpoint de API que no sea un simple pass-through CRUD
  3. Lógica comercial personalizada donde el cliente especificó el comportamiento exacto por escrito
  4. Cualquier cosa que escribió una IA que no leí completamente línea por línea

No pruebo:

  • Renderizado de UI (Las pruebas de snapshot nunca me han salvado ni una sola vez en nueve años. Ni una sola vez.)
  • Envoltorios de API de terceros donde el comportamiento externo está fuera de mi control
  • Scripts únicos que se ejecutan una vez y se eliminan
  • Hooks estándar de WordPress a menos que hagan algo inusual

Eso es todo. Sin filosofía grandilocuente. Solo una lista basada en dónde me he quemado.

---

El Flujo de Trabajo Que Realmente Funciona Para Mí

Ya que algunas personas han preguntado en las comunidades de Slack en las que estoy, aquí está la secuencia real:

  1. Escribe un comentario de especificación breve al principio del archivo, qué hace este módulo, qué no hace, casos límite que ya conoces.
  2. Le pido a Cursor que genere casos de prueba a partir de ese comentario antes de escribir ninguna implementación.
  3. Revisa esos casos de prueba. Elimina los tontos. Agrega cualquiera que la IA haya pasado por alto.
  4. Deja que Copilot o Cursor escriba la implementación.
  5. Ejecuta las pruebas. Fallarán. Arregla la implementación (no las pruebas).
  6. Lee el diff antes de hacer push, el código asistido por IA todavía necesita una revisión humana.

El paso 6 es innegociable. He atrapado tres bugs genuinamente graves en los últimos cuatro meses solo leyendo el diff lentamente antes de hacer push. Nada sofisticado. Solo leer.

El planteamiento original de Kent Beck sobre TDD nunca fue sobre cobertura al 100% o metodología perfecta. Se trataba de construir un ciclo de retroalimentación lo suficientemente rápido para atrapar errores antes de que se compundan. Esa idea, ciclos de retroalimentación rápidos, es más relevante ahora que en 2003. Porque la IA comete errores más rápido que cualquier desarrollador que haya contratado.

---

FAQ

¿Esto ralentiza tu velocidad de entrega?

Aproximadamente entre 10 y 15% en proyectos complejos. En los simples, quizá nada, la IA genera las pruebas tan rápido que la sobrecarga es mínima. Para proyectos donde un bug costaría dinero real corregir después del lanzamiento (y la mayoría de proyectos con dinero real califican), ese 15% vale cien veces más.

¿Y qué hay con TypeScript? ¿No es que el tipado fuerte reemplaza muchas pruebas?

Parcialmente. TypeScript detecta toda una clase de errores en tiempo de compilación que antes necesitabas pruebas para encontrar. Pero los tipos no prueban la lógica de negocio. No verifican que tu función de cálculo de descuentos aplique las reglas correctas para clientes mayoristas. Eso sigue siendo tu responsabilidad.

¿Deberían los desarrolladores junior usar herramientas de codificación con IA si no están escribiendo pruebas?

No. Opinión muy firme. Un desarrollador junior usando Copilot sin pruebas es esencialmente pilotar un avión en piloto automático sin entender cómo funciona el piloto automático ni cómo aterrizar manualmente. La IA producirá código que se ve de nivel senior, el junior no sabrá en qué partes desconfiar, y eventualmente tendrás un incidente en producción. Las pruebas al menos les dan un mecanismo para verificar el resultado que están aceptando.

¿Por qué dejaste de hacer pruebas en primer lugar, honestamente?

Burnout, parcialmente. Y un período donde cada proyecto era genuinamente simple y las pruebas genuinamente no se ganaban su lugar. El error fue no notar cuándo cambió la complejidad del proyecto y ajustar en consecuencia. Esa es la lección real, no "siempre prueba" o "nunca pruebes" sino saber en qué categoría cae un proyecto dado.

---

Escribir pruebas no solía sentirse como protección. Se sentía como papeleo. La IA cambió eso. No porque la IA sea mala, me ha hecho significativamente más rápido, sino porque introdujo una nueva clase de errores confiados, bien formateados, de aspecto plausible que no puedo atrapar leyendo código de la forma en que solía hacerlo. Las pruebas no son para la IA. Son para mí. Una función forzada para pensar en qué realmente necesito que el código haga antes de aceptar lo que sea que el modelo me entregue.

Desearía haberlo encuadrado de esa manera hace dos años.

Lecturas relacionadas: Cómo uso Claude Code diariamente como fundador que sigue entregando, herramientas, y SEO.

< BACK