La Suite de Pruebas como Supervisor de IA y Pruebas de Mutación en CI/CD
Cómo usar una suite de pruebas como supervisor determinista de agentes de IA: pruebas unitarias, de integración y de mutación aplicadas a un flujo agéntico Test-in-the-Loop dentro de pipelines de CI/CD.
El principio de «La suite de pruebas como supervisor» es uno de los pilares fundamentales de la ingeniería de software aplicada a la Inteligencia Artificial. Los modelos de lenguaje son elocuentes y pueden defender código con fallos sutiles o condiciones de carrera; por ello, la confianza debe validarse mediante ejecución determinista y no en lenguaje natural.
1. Los Tres Niveles de la Suite Supervisora
Para auditar y validar con precisión el código generado por un agente, la suite opera en tres niveles de verificación:
- Pruebas Unitarias (Lógica pura y casos borde):
- Validan funciones y métodos aislados de forma rápida.
- Fuerzan al agente a respetar tipos, contratos de entrada/salida y límites (edge cases).
- Pruebas de Integración (Contratos y flujos sistémicos):
- Verifican la interacción entre componentes (bases de datos, endpoints HTTP, colas).
- Aseguran que no se rompan dependencias ni se asuman comportamientos ficticios de librerías externas.
- Pruebas de Mutación (Supervisión de las pruebas):
- Introducen fallos intencionados o mutantes (invertir operadores, alterar booleanos).
- Si los tests pasan a pesar del mutante, este "sobrevive" y expone una brecha de cobertura real.
- Evitan el problema del falso verde, impidiendo aserciones vacías o superficiales.
2. El Flujo de Trabajo Agéntico: Test-in-the-Loop
El desarrollo asistido por IA se estructura como un bucle cerrado y autónomo:
[Prompt / Requerimiento]
│
▼
[Generación de Tests] ──► (TDD: Especificar comportamiento antes del código)
│
▼
[Generación de Código]
│
▼
[Ejecución de Tests] ────► ¿Falló? ──► [Log de Error al Prompt] ──┐
│ │
▼ (Pasa todos) │
[Pruebas de Mutación] │
│ │
├──► ¿Mutantes vivos? ──► [Añadir aserciones estrictas] ──┘
│
▼ (Score de mutación óptimo)
[Merge / Pull Request]
3. Validación Conversacional vs. Supervisión por Tests
| Factor | Validación por Conversación | Supervisión por Suite de Tests |
|---|---|---|
| Criterio de éxito | "Suena coherente y bien razonado" | Exit code 0 + Cobertura + Mutation score |
| Detección de regresiones | Manual y propensa a sesgos | Inmediata y reproducible |
| Efecto alucinado | Alto riesgo de pasar desapercibido | Se estrella contra las aserciones de tipos y comportamiento |
| Intervención humana | Requiere leer y razonar cada línea | Se enfoca en revisar arquitectura y diseño de tests |
Regla de oro: No le pidas al agente que te convenza de que su código funciona; dale una suite de pruebas rigurosa y pídele que la ponga en verde.
4. Pruebas de Mutación en Pipelines de CI/CD
Para evitar tiempos de cómputo excesivos en integración continua, se aplican tres estrategias:
- Mutación sobre el Diff: Analizar únicamente las líneas o archivos modificados en el Pull Request.
- Mapeo de Cobertura: Ejecutar solo los tests vinculados a las líneas mutadas.
- Umbral de Calidad (Mutation Score Threshold): Exigir una métrica mínima (ej. $\ge 80%$) para autorizar el paso del pipeline.
Herramientas por Ecosistema
| Lenguaje | Framework de Mutación | Estrategia de CI / Diff |
|---|---|---|
| TypeScript / JS | Stryker Mutator | Flags --incremental o --since |
| Python | mutmut / cosmic-ray |
Filtrado por archivo o ruta |
| Java / Kotlin | PITest (PIT) | Plugin pitest-git para Git diff |
| Rust | cargo-mutants |
Flag --in-diff nativo |
| Go | go-mutesting |
Ejecución por paquetes modificados |
5. Ejemplo de Pipeline: GitHub Actions (Node.js + Stryker)
name: Mutation Testing Gatekeeper
on:
pull_request:
branches: [ main, develop ]
jobs:
test-and-mutate:
runs-on: ubuntu-latest
steps:
- name: Checkout del repositorio
uses: actions/checkout@v4
with:
fetch-depth: 0 # Permite calcular el diff contra la rama principal
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Instalar dependencias
run: npm ci
- name: 1. Ejecutar Suite Rápida (Unitarias e Integración)
run: npm test
- name: 2. Ejecutar Pruebas de Mutación en archivos modificados
run: |
npx stryker run --since origin/main --score 80
env:
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }}
- name: Publicar reporte de mutantes supervivientes
if: failure()
uses: actions/upload-artifact@v4
with:
name: stryker-mutation-report
path: reports/mutation/mutation.html
6. Retroalimentación Automatizada al Agente
Cuando un mutante sobrevive en el pipeline, el log se envía de vuelta al modelo para corregir la suite:
[Pipeline CI/CD: Mutation Run]
│
├──► [Fallo: Mutante sobrevivió en auth.service.ts:42]
│ (Cambio: `token.exp > now` a `token.exp >= now`)
▼
[Extracción del Reporte / Log]
│
▼
[Prompt al Agente]:
"El test pasó pero sobrevivió un mutante en la línea 42 de auth.service.ts.
Añade una prueba que asevere específicamente el caso límite de expiración exacta."
│
▼
[Agente genera nueva aserción estricta] ──► [Re-ejecución CI]
Resultado: Se garantiza que el agente desarrolle pruebas orientadas al comportamiento real y no únicamente a la cobertura de líneas (line coverage).