Communitygithub.com

gpanakkal/crucible

Habilidad para agente que escribe pruebas unitarias en TypeScript que fallan correctamente cuando deben hacerlo.

¿Qué es crucible?

Crucible es una habilidad especializada para agentes de IA diseñada para escribir, corregir y auditar pruebas unitarias en proyectos TypeScript, utilizando Vitest para cobertura de código, fast-check para pruebas basadas en propiedades y Stryker Mutator para pruebas de mutación. Es compatible con plataformas como Claude Code, Cursor y Codex, y se activa automáticamente al detectar que el usuario solicita trabajar con pruebas unitarias, a menos que el proyecto haya optado por no usarlo mediante un archivo `.no-crucible` o una configuración explícita. La habilidad sigue un proceso riguroso: primero verifica la configuración del proyecto (paquetes instalados, configuraciones de Vitest y Stryker), luego evalúa las pruebas existentes midiendo cobertura y puntuación de mutación, y finalmente escribe nuevas pruebas asegurándose de que maximicen la cobertura de ramas y maten todos los mutantes posibles. Un aspecto clave es que las pruebas deben fallar cuando el código es erróneo o cuando los arbitrarios son demasiado amplios, tratando las pruebas como requisitos que se cumplen automáticamente cuando el usuario corrige el error. Esto evita el uso de `test.fails` o `.skip`, priorizando que el usuario sea claramente notificado de problemas.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add gpanakkal/crucible

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace crucible?

Cuándo usar esto

Cuando se solicite escribir, corregir o auditar pruebas unitarias en proyectos TypeScript.

Cuándo NO usar esto

Al escribir pruebas de extremo a extremo, integración, interfaz de usuario o simulación.

Exclusión voluntaria por proyecto

Antes de activar, verifica si el proyecto ha optado por no usar esta habilidad. Busca cualquiera de los siguientes:

  • Un archivo .no-crucible en la raíz del proyecto
  • "crucible": false en cualquier parte de AGENTS.md o .claude/settings.json

Si se encuentra alguna señal de exclusión, no actives la habilidad automáticamente; solo aplícala si el usuario lo solicita explícitamente en esta conversación.

Reglas

  • Los comandos de ejemplo usan pnpm, pero siempre usa el gestor de paquetes del proyecto.
  • No modifiques código de aplicación a menos que se te solicite explícitamente.
  • Cuando se te pida agregar pruebas, no modifiques las pruebas existentes.
  • Cuando se te pida corregir pruebas, no agregues nuevas pruebas.
  • Cuando se te pida auditar pruebas, corrige las pruebas existentes y luego agrega pruebas según sea necesario para cumplir con los criterios de prueba.

Criterios de prueba

Las pruebas unitarias deben:

  • Tener la máxima cobertura de ramas posible según Vitest.
  • Matar todos los mutantes eliminables, logrando la máxima puntuación de mutación posible en todo el código dentro del alcance de la instrucción (no solo lo cubierto por las pruebas). Los mutantes no eliminables impedirán una puntuación del 100%.
  • Ser basadas en propiedades siempre que sea posible, excepto si solo existen un puñado de casos de entrada. Por ejemplo, una función con un único parámetro booleano y sin entradas implícitas tiene solo dos casos de entrada posibles, así que no te molestes en hacerla basada en propiedades.
  • (si es basada en propiedades) tener arbitrarios que cubran todos los parámetros posibles y entradas implícitas. Es vital que no se excluyan casos que podrían ocurrir en producción. Si es necesario o no está claro, prefiere hacer los arbitrarios demasiado amplios.
  • Fallar si prueban código erróneo o si los arbitrarios se hacen intencionalmente demasiado amplios. Piensa en las pruebas como requisitos: deben nombrarse en consecuencia y deben pasar automáticamente tan pronto como el usuario corrija el error en el futuro después de que el usuario corrija la función y/o los arbitrarios. No uses test.fails/.skip; esto hace que sea menos obvio para el usuario que se necesita atención, por lo que las pruebas que pasan cuando no deberían es el error de mayor prioridad a evitar.

Verifica la cobertura de ramas y ejecuta las pruebas: pnpm exec vitest run src/foo.test.ts --coverage Verifica los mutantes supervivientes en el código que se está probando: pnpm exec stryker run --mutate "src/foo.ts"

Verificación de la configuración de pruebas

  1. Verifica que todos los siguientes paquetes estén instalados en el proyecto: vitest fast-check @stryker-mutator/core @stryker-mutator/vitest-runner @stryker-mutator/typescript-checker
  2. Verifica que las configuraciones de Vitest y Stryker incluyan/excluyan archivos correctamente. Stryker no debe verificar archivos que solo contengan datos de prueba.
  3. Verifica la configuración de Stryker:
    1. Usa el reportero clear-text (otros reporteros son opcionales).
    2. Usa el verificador de TypeScript y apunta correctamente al archivo de configuración de TypeScript.
  4. Busca cualquier otro problema de configuración que pueda causar problemas en el flujo de trabajo de escritura de pruebas.
  5. Informa los hallazgos al usuario.

Escritura de pruebas

Cuando se te pida escribir nuevas pruebas, NO MODIFIQUES EL CÓDIGO DE LA APLICACIÓN NI LAS PRUEBAS EXISTENTES.

Primero, evalúa las pruebas existentes siguiendo Evaluación de un módulo. Crea un nuevo archivo de informe usando la plantilla y registra allí la cobertura inicial y las puntuaciones de mutación.

Segundo, escribe las pruebas siguiendo este proceso exactamente:

Haz lo siguiente para cada función/método en la interfaz del módulo, terminando una función antes de comenzar la siguiente:

  1. Determina el propósito de la función examinando comentarios, su nombre, su firma de tipo y cómo se usa. Si no estás seguro, anótalo en el informe, omite escribir pruebas y pasa a la siguiente función.
  2. Toma nota de cualquier posible error en la implementación de la función.
  3. Basándote en su propósito, identifica cualquier suposición incorrecta que la función haga sobre sus parámetros y entradas implícitas, y anota cualquier caso de entrada que probablemente lleve a un comportamiento incorrecto de la función. Por ejemplo, una función que toma un número entero positivo pero no valida su entrada hace una suposición incorrecta sobre su entrada.
  4. NUNCA MODIFIQUES LAS PRUEBAS PREEXISTENTES. Si encuentras algún problema en las pruebas existentes, notifica al usuario sobre los problemas encontrados.
  5. Escribe nuevas pruebas haciendo lo siguiente: a. Usando fast-check, crea stubs de pruebas basadas en propiedades con arbitrarios que cubran todos los parámetros posibles y entradas implícitas de la función. Usa fc.asyncProperty + await fc.assert(...) cuando la función bajo prueba sea asíncrona. Si tienes dudas, prefiere hacer los arbitrarios demasiado amplios y menciónalo en el informe para que el usuario pueda corregirlos. Nombra las pruebas como descripciones del comportamiento deseado. b. Usando vitest, escribe aserciones dentro de los stubs que cubran cualquier valor devuelto y efectos secundarios como lanzar excepciones, mutar entradas, mutar/reasignar variables de ámbitos externos, etc. Asegúrate de que las pruebas afirmen el comportamiento deseado, detectando las suposiciones incorrectas/errores identificados anteriormente y fallando en consecuencia.
  6. Vuelve a verificar la cobertura: pnpm exec vitest run src/foo.test.ts --coverage
  7. Prueba de mutación solo la función actual: pnpm exec stryker run --mutate "src/foo.ts:<líneaInicio>-<líneaFin>"
  8. Revisa las pruebas recién escritas y repite los pasos 5a y 5b hasta que se cumplan los criterios de prueba (listados arriba) para la función.
  9. Actualiza el informe con una sección sobre esta función.

Después de escribir las pruebas para todas las funciones, verifica dos veces que hayas agregado secciones al informe para cada función y termina escribiendo la sección de resumen.

Auditoría de pruebas

Si se te solicita auditar el proyecto en su totalidad, verifica la cobertura de código y las puntuaciones de mutación a nivel de proyecto, y recomienda áreas para auditorías más detalladas o para agregar/actualizar pruebas. Inclina las recomendaciones hacia las áreas más importantes y propensas a errores del código base: lógica de negocio central, código impulsado por eventos y funciones complejas.

Si se te solicita auditar una parte del proyecto, busca módulos o funciones (dentro del alcance de la instrucción) que no tengan pruebas e informa de estos al usuario en el informe posterior a la auditoría.

Para cada módulo dentro del alcance de la instrucción que tenga pruebas, sigue Evaluación de un módulo. Luego, si algún criterio de prueba aún no se cumple después de las correcciones de la evaluación, sigue Escritura de pruebas para llenar los vacíos restantes.

Evaluación de un módulo

Usa este proceso siempre que necesites evaluar un archivo de prueba existente contra los criterios de prueba, tanto antes de escribir nuevas pruebas como al auditar.

  1. Verifica la cobertura de código usando Vitest: pnpm exec vitest run src/foo.test.ts --coverage.
  2. Verifica los mutantes supervivientes usando Stryker Mutator: pnpm exec stryker run --mutate "src/foo.ts".
  3. Para cada función en el módulo que tenga pruebas:
    • Para las pruebas basadas en propiedades:
      • Busca entradas que la función aceptaría sin lanzar una excepción o devolver un valor de error, pero que no pueden ser generadas por los arbitrarios. Amplía los arbitrarios según sea necesario para incluir dichas entradas.
      • Busca entradas que no estén cubiertas por los arbitrarios, especialmente entradas implícitas como campos de clase, variables globales, fecha/hora y números generados aleatoriamente. Agrega arbitrarios para estas.
    • Corrige cualquier error en las implementaciones de mocks.
    • Busca cuellos de botella de rendimiento.
  4. Registra la cobertura y las puntuaciones de mutación, junto con cualquier hallazgo, en el informe.

Informes de pruebas

Formatea los informes según la plantilla a continuación. Si no hay nada que informar en una subsección de función, simplemente escribe "n/a". Genera el informe en un archivo Markdown en debriefs/.

Informe: {nombreMódulo/nombreArchivo} {aaaa-mm-dd}

Resumen

Cobertura (ramas) Antes: X% → Después: Y% Líneas que no pudieron cubrirse: {rangos de líneas}

Puntuación de mutación (total) Antes: X% → Después: Y%

Problemas

{lista de viñetas de suposiciones incorrectas, errores encontrados, problemas en las pruebas y pruebas fallidas. Cada elemento de la lista debe comenzar con la ruta relativa a la raíz del proyecto y el número(s) de línea donde se encontró el problema}

{nombreFunción}

Propósito de la función {una oración que describa lo que se supone que hace la función} (confianza: alta | incierta) {si es incierta: qué no está claro y por qué}

Suposiciones incorrectas encontradas

  • (línea {número/rango de línea}): {suposición sobre el tipo/rango/forma de entrada que la función no valida}

Errores encontrados en la implementación

  • (línea {número/rango de línea}): {descripción + número de línea}

Problemas encontrados en pruebas preexistentes

  • (línea {número/rango de línea}): {descripción del problema + nombre de la prueba}

Casos de prueba escritos

  • {breve descripción de cada propiedad/invariante probado}

Pruebas fallidas

  • (línea {número/rango de línea}): {nombre de la prueba + razón}

Mutantes no eliminables

  • (línea {número/rango de línea}): {breve descripción}

Skills relacionados