Por qué un bug de Cursor no es un bug cualquiera
Una persona que escribe ese mismo cambio lleva consigo un contexto que el editor nunca ve. Recuerda que el panel de ajustes lee de una caché que hay que invalidar, que el botón de carga está deshabilitado hasta que se selecciona un archivo, que cierto endpoint devuelve un array vacío en lugar de un 404 cuando no hay coincidencias. Cursor trabaja con los archivos que abriste y el texto que escribiste. Todo lo que queda fuera de esa ventana es una suposición.
Así que el modo de fallo no es la sintaxis incorrecta. Es un cambio localmente correcto y globalmente equivocado. La función hace exactamente lo que dice. Se la llama en el momento equivocado, o deja un resto de estado sin limpiar, o asume una estructura que la API dejó de devolver hace dos sprints.
Las pruebas unitarias no lo detectan, porque se escriben sobre las mismas suposiciones con las que se escribió el código. Si el agente escribió ambas cosas, coinciden entre sí y discrepan de tu producto.
De dónde vienen realmente los bugs de Cursor
Tres lugares concentran la mayor parte.
Estado de la interfaz
Un formulario se envía, pero la lista que está detrás no se actualiza.
Un modal se cierra y deja bloqueado el scroll del body.
Un botón sigue habilitado mientras una petición ya está en curso, así que un doble clic crea dos registros.
Flujos asíncronos
La pantalla se renderiza antes de que lleguen los datos y nunca vuelve a renderizarse.
Se lanza una tarea en segundo plano, pero nada la espera, así que el siguiente paso lee valores desactualizados.
Una ruta de error se resuelve en silencio y el usuario ve un mensaje de éxito por un trabajo que falló.
Límites de integración
El payload coincide con la definición de tipos, pero no con lo que el servicio acepta en realidad.
Se da por hecha la autenticación porque estaba presente en la sesión que vio el agente.
La paginación, los estados vacíos y los límites de tasa se manejan en el sistema de tipos y en ningún otro lugar.
Lo que todos tienen en común es que solo se ven ejecutando la aplicación y usándola. Leer el diff no revela ninguno de ellos, y tampoco lo hará una suite de pruebas que nunca abre un navegador.
Cómo detectar los bugs de Cursor antes de hacer merge
La verificación tiene que ocurrir contra la aplicación desplegada, manejada como la manejaría una persona, y el resultado tiene que volver en un formato sobre el que el agente pueda actuar. De lo contrario, encontraste el bug, pero quien lo arregla sigues siendo tú.
Tres cosas tienen que cumplirse. Ninguna es difícil; dejar fuera cualquiera de ellas es lo que impide que el ciclo se cierre.
El agente tiene que saber cómo verificar
La configuración inicial instala una skill de verificación en el propio agente de programación, para que sepa cómo crear, ejecutar y diagnosticar pruebas en lugar de adivinar a partir de un README. Escribe un archivo de instrucciones donde tu editor ya lo busca, lo que significa que Cursor lo toma de .cursor/rules/ igual que Claude Code lee su propio directorio de skills. Se admiten ocho editores, lo que importa en un equipo donde no todos usan el mismo.
Terminal
npm install -g @testsprite/testsprite-cli
testsprite setup
Puedes hacer lo mismo desde el panel de TestSprite si prefieres no instalar nada en local. Todo lo demás que puede hacer la CLI está en el repositorio de la CLI.
La verificación tiene que apuntar a la aplicación desplegada, no a un mock
Dirige una ejecución al entorno donde el cambio está publicado. El agente abre la aplicación, recorre el comportamiento como lo haría un usuario y reporta lo que ocurrió de verdad, en lugar de si se cumplió una aserción en un sandbox. Los mocks no pueden producir esa señal, y por eso conviven tan cómodamente una suite unitaria en verde y una funcionalidad rota.
El fallo tiene que volver como algo que el agente pueda usar
Esta es la parte que decide si el ciclo se cierra. Un fallo que llega como una captura de pantalla en un panel obliga a que una persona lo lea, lo interprete y escriba un prompt. Un fallo que llega como un único paquete coherente con lo que se intentó, lo que hizo la aplicación y dónde se desvió es algo que el agente puede tomar y aprovechar directamente. La siguiente iteración parte de la evidencia y no de tu descripción de la evidencia.
Haz que ocurra sin que nadie tenga que acordarse
Una verificación que ejecutas a mano es una verificación que te saltas el día que vas con prisa, que es justo el día en que la necesitas. Hay dos formas de automatizarla, y cuál te conviene depende de quién sea el dueño de tu pipeline.
La GitHub App es un webhook que configuras en el panel de TestSprite. Escucha el evento de despliegue que tu pipeline ya produce, así que nada cambia en tu repositorio.
GitHub Actions coloca el paso dentro de tu propio workflow, configurado desde la terminal.
Vale la pena entender el modelo aunque nunca toques la configuración. La integración no compila ni despliega tu aplicación, y no añade ni edita archivos de workflow. Escucha el evento de despliegue que tu pipeline ya produce y toma «la nueva build está publicada en esta URL» como la señal para iniciar una ejecución. Los resultados vuelven donde está ocurriendo el trabajo: como un comentario en el pull request o una verificación en el commit.
Dos decisiones determinan si resulta útil, y ambas son cuestión de criterio más que de configuración.
Qué momento cuenta como listo. Elige el evento que se dispara después de que el despliegue está publicado, no el que se dispara cuando arranca la build. Un evento que llega demasiado pronto apunta la ejecución a una URL que todavía no está en pie, y todas las pruebas fallan por un motivo que no tiene nada que ver con tu código. Esta es, con diferencia, la forma más habitual de que la configuración salga mal.
Si la verificación es informativa o bloqueante. Un comentario en el pull request informa. Una verificación obligatoria bloquea el merge. Empieza en modo informativo durante una semana para ver qué detecta y luego decide. Hacerla bloqueante el primer día, antes de que nadie confíe en ella, es la forma de que una verificación útil acabe desactivada.
Una nota práctica si tus previews viven en una plataforma como Vercel o Netlify: cada proveedor nombra las URL de preview de forma distinta, así que la integración acepta un patrón en lugar de una dirección fija y completa la rama o el pull request en cada ejecución.
Cómo encaja esto junto a tus pruebas actuales
Esto es verificación de comportamiento contra el producto en ejecución, así que complementa a las pruebas unitarias locales rápidas en lugar de sustituirlas. Quédate con las pruebas unitarias para la lógica y deja que esto cubra lo que ellas, por su propia estructura, no pueden ver: si la funcionalidad funciona cuando la maneja un usuario real.
Una nota sobre el patrón más amplio
Nada de esto es específico de Cursor. La misma brecha aparece con cualquier asistente que escribe código más rápido de lo que una persona puede leerlo, y por eso merece la pena construir el paso de verificación una vez y reutilizarlo en todos los editores. En una tabla de clasificación abierta en la que varios agentes construyeron la misma aplicación, el modelo más barato del grupo entregó la aplicación más correcta cuando este ciclo de verificación estaba en marcha, a la mitad del costo de la propuesta más cara. La lección no fue que un modelo sea mejor. Fue que un modelo con una señal de retroalimentación que funciona le gana a un modelo más potente sin ella.
Dónde encaja TestSprite en el ciclo de Cursor
TestSprite es la mitad de verificación. Cursor escribe el cambio; TestSprite abre la aplicación desplegada, recorre el comportamiento como lo haría un usuario y reporta lo que ocurrió de verdad. Ninguno intenta hacer el trabajo del otro, y esa separación es justo el punto: quien escribe un cambio no es la parte adecuada para confirmarlo.
De ahí se derivan tres cosas para un equipo que publica código escrito con Cursor. La cobertura deja de depender de que alguien encuentre tiempo para escribir pruebas, porque los casos se generan a partir de tu producto y se refinan en lenguaje natural. Los rediseños cosméticos dejan de poner la suite en rojo, porque un paso es una intención y no una ruta por el DOM. Y un fallo vuelve como un único paquete sobre el que el agente puede actuar, así que la siguiente iteración parte de la evidencia en lugar de tu descripción de ella.
Lo que puedes esperar el primer día son los flujos que te daría vergüenza romper, ejecutándose en cada pull request, con un resultado que señala la desviación. Lo que no hace es revisar tu código ni sustituir las pruebas unitarias locales rápidas: funciona junto a ambos.
¿Por qué pasan las pruebas del propio Cursor cuando la funcionalidad está rota?
Porque las pruebas y el código salieron de las mismas suposiciones. Si el agente creía que un endpoint devuelve un array vacío y escribió tanto el handler como la prueba en torno a esa creencia, ambos coinciden entre sí. Solo ejecutar la aplicación real contra el servicio real deshace el empate.
¿Necesito un equipo de QA para configurar esto?
No. La configuración es un comando de la CLI y la instalación de la GitHub App. Está pensada para equipos en los que los desarrolladores son las únicas personas que llegarán a mirar el resultado de una prueba.
¿Necesita acceso a mi código fuente?
La verificación se ejecuta contra tu aplicación desplegada a través de su interfaz. El permiso de escritura en GitHub se usa para publicar resultados en los pull requests y los commits, no para subir código ni modificar archivos de workflow.
¿Qué pasa con las pruebas cuando la interfaz cambia a propósito?
Una prueba ligada a un flujo de negocio, y no a un elemento concreto, sobrevive a un rediseño que no cambia el flujo. Cuando cambia el flujo en sí, eso es un comportamiento nuevo y necesita un caso nuevo o actualizado, que el agente puede generar a partir del cambio.
¿Puedo ejecutar esto en una rama sin afectar la suite principal?
Las pruebas pertenecen a la aplicación y no a una rama de git, así que hay una única suite canónica. Elige el disparador de pull request si quieres verificaciones por rama, y el de push si quieres un único entorno compartido verificado después de cada merge.
Deja de leer el diff. Ejecuta la aplicación.
Los bugs de Cursor se esconden en el estado, los tiempos y los límites de integración, que son justo los lugares a los que no llegan una lectura estática ni una prueba con mocks. Pon la verificación en manos del agente, apúntala a la build desplegada y deja que el pull request te diga si el cambio funciona antes de que alguien haga merge.