coverage-orchestrator-cli-new
v1.5.3
Published
CLI to orchestrate AI agents for automated Java test generation based on JaCoCo coverage reports
Maintainers
Readme
Coverage Orchestrator CLI
Coverage Orchestrator CLI es un CLI en Node.js que convierte un reporte XML de JaCoCo en un backlog priorizado y “AI-friendly” de misiones para aumentar la cobertura de tests unitarios Java de forma eficiente.
Está pensado para equipos que trabajan con microservicios Java (Maven o Gradle) y quieren:
- identificar dónde las mejoras de cobertura tienen mayor ROI,
- generar instrucciones claras y repetibles para un agente de IA (o un developer),
- iterar rápidamente hasta alcanzar un objetivo (por ejemplo 60% de cobertura global).
Tabla de contenidos
- Conceptos clave
- Requisitos
- Instalación
- Quickstart
- Cómo funciona
- Referencia del CLI
- Cache y modelo de estado
- Workflow recomendado
- Consejos para usarlo con un agente de IA
- Troubleshooting
- Limitaciones
- Roadmap
- Contribuir
- Licencia
Conceptos clave
Misión
Una misión es un documento en Markdown que imprime next y que incluye:
- ruta objetivo del Java source (best-effort),
- ruta recomendada del test (best-effort),
- detección de una suite
<Clase>Test.javaexistente en la ruta convencional, cuando la hay, - métodos con 0% de cobertura de línea (según JaCoCo),
- un prompt adaptado para generar tests (Mockito + estilo de aserciones detectado).
PriorityScore (ROI)
Para cada clase, el CLI calcula:
MissedLines= counter de JaCoCoLINE.missedComplexity= counter de JaCoCoCOMPLEXITY.missed + COMPLEXITY.coveredPriorityScore = MissedLines * Complexity
Un score alto significa: “testear esta clase probablemente moverá más la cobertura”.
Auto-DONE (Smart Analyze)
En cada analyze, las clases se etiquetan automáticamente basándose en evidencia del XML:
- si
coveragePct >= 80→status: DONE,autoVerified: true - si no →
status: TODO
Esto permite iterar simplemente regenerando el reporte y re-ejecutando analyze.
Requisitos
- Node.js 20+
- Un proyecto Java que genere JaCoCo XML
- Maven: típicamente
target/site/jacoco/jacoco.xml - Gradle: típicamente
build/reports/jacoco/test/jacocoTestReport.xml
- Maven: típicamente
Instalación
Opción recomendada: instalación global
Instala el CLI globalmente una vez y usa el binario coverage-orchestrator en todos los repositorios Java:
npm install -g coverage-orchestrator-cli-new
coverage-orchestrator --helpNo uses
npxen flujos Axet: puede fallar al resolver el binario. El paquete npm escoverage-orchestrator-cli-newy expone el comando globalcoverage-orchestrator.
Desarrollo local (este repositorio)
npm install
node src/index.js --helpPara simular un binario global desde este repo:
npm link
coverage-orchestrator --helpPara eliminar el link:
npm unlink -g coverage-orchestrator-cli-newQuickstart
1) Genera el reporte JaCoCo en tu proyecto Java
Maven:
mvn test jacoco:reportGradle:
./gradlew test jacocoTestReport2) Analiza el reporte
Si lo ejecutas desde el root del microservicio, el CLI puede auto-detectar rutas comunes:
coverage-orchestrator analyzeO puedes pasar la ruta explícita:
coverage-orchestrator analyze --path "C:\\path\\to\\jacoco.xml"3) Pide la siguiente misión
coverage-orchestrator next4) Implementa tests y repite
Regenera el JaCoCo XML → re-ejecuta analyze → ejecuta next otra vez.
Cómo funciona
1) Detectar el root del microservicio (projectRoot)
Dada la ruta al jacoco.xml, el CLI sube directorios hasta encontrar:
pom.xml, obuild.gradle/build.gradle.kts
Ese directorio se considera el projectRoot.
2) Detectar el entorno (best-effort)
Desde el projectRoot, el CLI detecta:
- build tool: Maven / Gradle
- versión Java (si se puede detectar)
- versión de Spring Boot (si se puede detectar)
- librería de aserciones:
- AssertJ / Hamcrest / default JUnit 5 Assertions
- uso de Lombok (
usesLombokboolean)
3) Parsear el JaCoCo XML
El parser normaliza el XML a paquetes/clases/métodos y counters.
El CLI está diseñado para ser fiel al reporte: procesa todas las clases presentes en el XML. Los filtros se aplican únicamente en la capa de orquestación (p. ej.
--minCoverageToIgnore,--ignore), no en el parser.
4) Puntuar clases y construir misiones
El orchestrator:
- calcula
PriorityScore, - opcionalmente ignora clases con cobertura muy alta (default
> 90%, configurable), - auto-etiqueta DONE/TODO usando el umbral 80% por clase,
- ordena por prioridad y guarda estado en un fichero de cache.
Referencia del CLI
El paquete expone el binario:
coverage-orchestrator <command> [options]init
Instala el workflow autónomo de cobertura en el repositorio Java en el que se ejecuta el comando.
coverage-orchestrator initComportamiento:
- busca hacia arriba el primer directorio que contenga
pom.xml,build.gradleobuild.gradle.kts; - crea
<projectRoot>/.axetrules/workflows/unit-tests.md; - crea o actualiza
<projectRoot>/.gitignorede forma idempotente con:# Axet & Coverage Orchestrator.axetrules/.coverage-cache.json.axet/build-gradle-jacoco.log;
- no sobrescribe un workflow local existente por defecto;
- el workflow instalado protege las suites de tests preexistentes: deben extenderse con nuevos casos, no sustituirse.
Para reemplazar explícitamente el workflow instalado por la versión incluida en el CLI:
coverage-orchestrator init --forceSi no se detecta Maven ni Gradle, usa el directorio actual como destino e informa de ello.
analyze
Escanea el JaCoCo XML y guarda un estado local (cache).
coverage-orchestrator analyze [--path <jacoco.xml>]Opciones:
--path <path>: ruta al JaCoCo XML (opcional; auto-detecta rutas comunes si se omite)--minCoverageToIgnore <pct>: ignora clases con cobertura de líneas> pct(default90)--ignore <pattern...>: ignora clases cuyo FQCN contenga alguno de los substrings (opt-in)--include <pattern...>: fuerza incluir clases incluso si coinciden con reglas de ignore (opt-in)
Outputs:
- imprime dónde se guardó el cache,
- imprime conteo TODO/DONE.
next
Imprime la siguiente misión en Markdown.
coverage-orchestrator nextOpciones:
--sourceRoot <path>(defaultsrc/main/java)--testRoot <path>(defaultsrc/test/java)
Comportamiento:
- elige la clase con mayor prioridad cuyo
status !== DONE; - inyecta el comando aislado exacto para ejecutar solo la clase de test objetivo y generar JaCoCo;
- lee el fuente Java objetivo cuando está disponible e incluye dependencias de campos
@Autowired, constructores y colaboradores como@Mocksugeridos, junto al SUT como@InjectMocks; - detecta
<Clase>Test.javadentro de--testRoot; si existe, la misión obliga a conservar sus tests, fixtures, helpers e imports y a añadir solamente los casos que faltan; - prohíbe los stubs y los micro-incrementos de 2-3 tests;
- exige una única edición con una suite completa de 8 a 20 tests cuando se crea desde cero, o añade los casos no redundantes que falten si ya existe una suite, cubriendo happy path, nulos/límites y errores/excepciones;
- fija como objetivo superar el 80% de cobertura de líneas de la clase en la misión y dejarla
DONEcuando JaCoCo lo confirme.
mark-done (legacy)
Marca manualmente una clase como DONE. Se mantiene por compatibilidad, pero el workflow recomendado es:
escribir tests → generar JaCoCo →
analyze→next
coverage-orchestrator mark-done com.foo.BarServicesummary
Muestra un resumen global de cobertura calculado desde el cache.
coverage-orchestrator summary
coverage-orchestrator summary --jsonCache y modelo de estado
Dónde se guarda el cache
El cache se guarda por microservicio/módulo (aislamiento total):
<moduleRoot>/.coverage-cache.json
Cómo se decide el moduleRoot:
- En
analyze, si pasas--path, el CLI sube directorios desde eljacoco.xmly usa el primer directorio que contengapom.xmlobuild.gradle(.kts)(la raíz más cercana). Ese es elmoduleRoot. - Si NO pasas
--path, el CLI intenta auto-detectar eljacoco.xmlen el directorio actual y, si no lo encuentra, hace una búsqueda recursiva limitada.
Importante (monorepo):
nextysummarysolo buscan el cache en el directorio actual (process.cwd()).- Si no existe
.coverage-cache.jsonen la carpeta actual, el CLI pide ejecutar el comando desde dentro del módulo o correranalyzeahí primero. - Si detecta un cache en el directorio padre,
analyzeemite una advertencia y no lo mezcla ni lo modifica.
Forma del cache (simplificada)
{
"version": 1,
"generatedAt": "2026-04-23T00:00:00.000Z",
"xmlPath": "C:\\path\\to\\jacoco.xml",
"env": {
"language": "Java",
"buildTool": "Maven",
"version": "17",
"framework": "Spring Boot",
"frameworkVersion": "3.2.0",
"assertionLib": "AssertJ",
"usesLombok": true
},
"items": [
{
"className": "com.acme.FooService",
"metrics": { "coveragePct": 12.3, "missedLines": 100, "coveredLines": 14, "complexityTotal": 20 },
"priorityScore": 2000,
"status": "TODO",
"attempts": 0,
"autoVerified": false
}
]
}Workflow recomendado
1) Instala las instrucciones para el agente
Desde el root del módulo Java:
coverage-orchestrator initEl workflow queda en .axetrules/workflows/unit-tests.md. Es configuración local; init gestiona de forma idempotente .axetrules/, el cache y los artefactos locales de Axet/Coverage Orchestrator en el .gitignore del proyecto objetivo.
2) Genera cobertura y crea la línea base
- Maven:
mvn test jacoco:report - Gradle:
./gradlew test jacocoTestReport
Después, sincroniza y consulta el estado:
coverage-orchestrator analyze --minCoverageToIgnore 101
coverage-orchestrator summary3) Ejecuta una misión por vez
coverage-orchestrator nextSi la misión detecta una suite existente, ábrela y conserva sus tests, fixtures, helpers e imports; añade en ella únicamente los casos que cubran los huecos restantes. Si no existe, crea una única suite masiva de 8 a 20 tests para todos los métodos al 0%, cubriendo happy path, nulos/límites y excepciones. El objetivo por misión es superar el 80% de líneas de la clase en el primer ciclo. Ejecuta exclusivamente el comando aislado incluido en la misión y, cuando pase, repite analyze seguido de summary. No uses clean, la suite global, --no-daemon ni una estrategia de micro-tests durante la implementación de una misión.
Política de reintentos y estancamiento
- El workflow limita a 3 los intentos de corregir un error de compilación o ejecución producido por un cambio.
- El CLI conserva
attemptspor clase. Si la misión prioritaria se analiza sin mejora de cobertura, incrementa el contador. - A los 5 intentos sin avance, la clase queda como
SKIPPEDconskipReason: MAX_ATTEMPTS;nextseleccionará otra misión. - Las clases
SKIPPEDrequieren revisión humana. No se deben marcar comoDONEmanualmente para ocultar falta de evidencia.
Consejos para usarlo con un agente de IA
- Trata la misión como el “contrato”: define la clase objetivo, los métodos 0% y la ubicación del test.
- El prompt ya incluye:
- JUnit 5 y tu estilo de aserciones (
AssertJ/Hamcrest/JUnit 5 Assertions); - Mockito con
@Mocksugeridos desde el fuente objetivo y el SUT como@InjectMocks; - el comando aislado para obtener feedback rápido y actualizar el reporte JaCoCo;
- la detección de una suite existente y la regla de preservarla, añadiendo únicamente los casos nuevos necesarios;
- la regla de generación masiva: 8-20 tests one-shot al crear una suite, con objetivo superior al 80% por clase y sin micro-incrementos.
- JUnit 5 y tu estilo de aserciones (
- Si la clase usa Lombok (
env.usesLombok: true), considera pedir al agente:- evitar testear boilerplate generado por Lombok salvo necesidad,
- enfocarse en lógica y comportamiento observable.
Troubleshooting
analyze no encuentra jacoco.xml
Si no pasas --path, el CLI solo busca rutas comunes:
target/site/jacoco/jacoco.xml(Maven)build/reports/jacoco/test/jacocoTestReport.xml(Gradle)
Pasa la ruta manualmente:
coverage-orchestrator analyze --path "<absolute-or-relative-path>"Cache no encontrado al ejecutar next
El cache está en <projectRoot>/.coverage-cache.json.
Recomendado:
- ejecutar
nextdesde el root del microservicio, o - ejecutar
analyzeantes (imprime la ruta del cache).
Limitaciones
- Los paths de source/test son best-effort: JaCoCo provee
package+sourcefilename, pero monorepos/multi-módulo pueden requerir ajustar--sourceRoot/--testRoot. - La detección de entorno es heurística:
- herencia de parent multi-módulo Maven y propiedades con placeholders pueden dejar
env.version/env.frameworkVersioncomonull.
- herencia de parent multi-módulo Maven y propiedades con placeholders pueden dejar
- La lista de métodos “0% coverage” puede incluir métodos sintéticos en casos extremos. Actualmente filtramos
$,<init>y<clinit>.
Roadmap
- Mejorar detección de Java/Spring en multi-módulo (resolver parent chain / propiedades).
- Detectar JUnit 4 vs JUnit 5 y adaptar prompts.
- Mejorar la extracción de dependencias para cubrir constructores Lombok, anotaciones personalizadas e imports complejos.
- Documentar mejor el output de
summaryy añadir reporting más accionable.
Contribuir
- Haz fork del repo
- Crea una rama de feature
- Ejecuta:
npm install node src/index.js --help - Abre una PR con una descripción clara + ejemplos before/after
Licencia
ISC
