Ir al contenido

Mutation Testing

Guia de Mutation Testing — Tests que Realmente Detectan Bugs

Sección titulada «Guia de Mutation Testing — Tests que Realmente Detectan Bugs»

Version: 1.0.0 | Marzo 2026 Framework: AI Software Factory OS v7.7 Prerequisito: Evals_Framework_Guide.md, f07_tevv skill


La cobertura de lineas es una metrica engañosa. Un test puede cubrir una linea sin verificar que esa linea hace lo correcto.

Datos reales (2026):

  • Estudio HumanEval-Java: AI genera tests con 100% line coverage pero solo 4% mutation score
  • Los tests generados por AI describen lo que el codigo HACE, no lo que DEBERIA hacer
  • Meta: engineers aceptaron 73% de mutation tests generados por LLMs (ACH tool)
  • Diffblue: 81% line coverage + 61% mutation coverage (autonomo) vs developer con Claude Code: 32% line + 24% mutation en 2 horas

Conclusion: Coverage sin mutation testing no es una metrica de calidad — es una metrica de actividad.


Mutation testing introduce cambios pequenos (mutantes) en el codigo fuente y verifica que los tests detecten esos cambios:

Codigo original: Mutante:
───────────────── ─────────────────
function isAdult(age) { function isAdult(age) {
return age >= 18; → return age > 18; // >= cambio a >
} }
Test: isAdult(18) === true
Resultado: El test PASA con el mutante → el mutante SOBREVIVIO
→ El test NO verifica el boundary condition (edad exacta 18)

Mutation Score = mutantes killed / total mutantes × 100


CategoriaOperadorOriginal → MutadoQue detecta
RelacionalROR>>=, <<=, ==!=Boundary conditions
AritmeticoAOR+-, */Calculos incorrectos
LogicoLCR&&||, !xxLogica booleana
RetornoRVRreturn truereturn falseValores de retorno
EliminacionSDLEliminar statementSide effects
ConstanteCOR01, """mutant"Magic numbers
NullNULreturn objreturn nullNull safety
VoidVMCEliminar llamada voidMetodos con efectos

Ventana de terminal
# Instalacion
npm install -D @stryker-mutator/core \
@stryker-mutator/typescript-checker \
@stryker-mutator/vitest-runner # o jest-runner
# Configuracion (stryker.config.json)
{
"mutate": ["src/**/*.ts", "!src/**/*.test.ts"],
"testRunner": "vitest",
"checkers": ["typescript"],
"reporters": ["clear-text", "html", "json"],
"thresholds": { "high": 80, "low": 60, "break": 50 }
}
# Ejecutar
npx stryker run
Ventana de terminal
# Instalacion
pip install mutmut
# Ejecutar
mutmut run --paths-to-mutate=src/
# Ver resultados
mutmut results
mutmut show 42 # ver mutante especifico
# Exportar
mutmut junitxml > mutation-report.xml
pom.xml
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.17.0</version>
<configuration>
<targetClasses>com.example.*</targetClasses>
<mutationThreshold>60</mutationThreshold>
</configuration>
</plugin>
target/pit-reports/index.html
mvn org.pitest:pitest-maven:mutationCoverage
Ventana de terminal
go install github.com/zimmski/go-mutesting/cmd/go-mutesting@latest
go-mutesting ./...

  • Logica de negocio (services, handlers, domain)
  • Calculos criticos (billing, scoring, classification)
  • Validaciones (input validation, auth checks)
  • Integraciones (API clients, DB queries)
  • DTOs y tipos (solo estructura, no logica)
  • Migrations (esquema de DB, no testeable con mutation)
  • Config files (valores fijos, no logica)
  • Test files (no mutar tests contra si mismos)
  • Boilerplate generado (Prisma client, gRPC stubs)
  • Stryker: timeoutMS: 10000 (10s por mutante, default)
  • mutmut: --timeout-multiplier 2 (2x el tiempo normal del test)
  • PIT: <timeoutConstant>5000</timeoutConstant>

F06 (Build)
↓ tests pasan (unit + integration)
F07 (TEVV)
↓ coverage >= 80%
↓ mutation score >= 60% ← NUEVO
↓ eval baseline cumplido
Gate E (calidad)
↓ todo pasa
F08 (Security)
Script OSSFIAComo complementa mutation testing
spec-first-check.pyVerifica que tests EXISTEN
dora-metrics.pyMide rework rate
fab-eval-builders.pyEvalua builder quality
compliance-linter.pyVerifica artefactos F07
# Agregar a .github/workflows/test.yml
- name: Mutation Testing (semanal)
if: github.event.schedule || contains(github.event.head_commit.message, '[mutation]')
run: |
npx stryker run --reporters json
SCORE=$(jq '.mutationScore' < reports/mutation/mutation.json)
echo "Mutation score: $SCORE%"
if (( $(echo "$SCORE < 60" | bc -l) )); then
echo "::warning::Mutation score below 60% threshold"
fi

Meta desarrollo Automated Compliance Hunting (ACH) que usa LLMs para mutation testing a escala en Facebook, Instagram, WhatsApp:

  1. LLM analiza el codigo fuente y genera mutaciones inteligentes (no aleatorias)
  2. LLM genera tests que detectan esas mutaciones especificas
  3. Engineers revisan y aprueban (73% acceptance rate)
  4. Los tests se agregan al suite automaticamente

Ventaja sobre mutation testing tradicional: mutaciones targetted basadas en el entendimiento semantico del LLM, no permutaciones aleatorias.

Como replicar en OSSFIA:

1. Agent analiza src/ con code_reviewer skill
2. Agent identifica paths criticos sin tests fuertes
3. Agent genera mutaciones inteligentes del codigo
4. Agent genera tests que matan esas mutaciones
5. Human review de los tests generados
6. Merge + baseline de mutation score actualizado

MetricaTargetExcelenteAceptableCritico
Mutation Score>= 60%>= 80%60-79%< 40%
Killed MutantsMaximizar> 80%> 60%< 40%
Survived MutantsMinimizar< 20%< 40%> 60%
Timeout Mutants< 10%< 5%< 10%> 20%
No Coverage< 5%< 2%< 5%> 10%

Mutation testing tiene diminishing returns:

  • Ir de 60% a 80% = alto valor (elimina tests debiles criticos)
  • Ir de 80% a 95% = bajo valor (mutantes restantes son edge cases)
  • Ir de 95% a 100% = costo prohibitivo (mutantes equivalentes, timeouts)

Target recomendado: 60% para produccion, 80% para codigo critico (billing, auth, safety).


ContextoFrecuenciaRazon
PR con logica nuevaEn el PR (solo archivos cambiados)Feedback rapido
Sprint semanalSemanal (full suite)Baseline tracking
ReleasePre-release (full suite)Confidence check
Post-incidentDespues de bug en produccionVerificar que tests previenen recurrencia

Companion del AI Software Factory OS v7.7 See: mutation_testing skill, Evals_Framework_Guide.md, f07_tevv skill