Skip to main content
Glama
README.md
# QA MCP

Servidor MCP para automatizar generación de artefactos de QA:
- tests API con Rest Assured (`generateRestTests`): Java + JUnit 5 + Rest-Assured, cubriendo todos los resultados de cada endpoint, con ejecución/feedback (`runRestTests`)
- tests E2E con Cypress (`generateE2ETests`) y ejecución/feedback (`runE2ETests`)
- documentación ETP en Excel (`exportETPAsExcel`) y Word (`exportETPAsWord`)
- informe de evidencias Rest Assured en Excel (`exportRestTestsAsExcel`)
- autocompletado de `rf-cu.md` (`autoCompleteRfCu`)

Usa `mcp.config.json` en la raíz del proyecto para localizar OpenAPI, frontend, rutas de salida y plantillas.

## Generación de tests REST (`generateRestTests`)

Genera **tests de integración Java + JUnit 5 + Rest-Assured** guiados por LLM. Todo su comportamiento (reglas, convenciones y alcance) está definido en **`prompts/rest.md`**, configurable con `prompts.rest` en `mcp.config.json`.

- **Entrada**: el contrato `openApi` (se parsean todos los `paths`, parámetros, request bodies y **todos los códigos de respuesta declarados**) y el **código real del backend** (`backend.root`), del que se derivan rutas efectivas, `context-path`, validaciones, cuerpos de error de `@ControllerAdvice`, reglas de negocio (404/409) y seguridad (401/403).
- **Cobertura**: un `@Test` como mínimo **por cada resultado posible de cada endpoint**. El servidor calcula ese mínimo y lo verifica.
- **Salida**: un fichero `*ApiTest.java` por grupo funcional (tag de OpenAPI o primer segmento de la ruta) dentro de `restTests`, en el paquete deducido del backend (`<paquete-raíz>.api`).
- **Alcance cerrado**: la tool **solo crea o modifica tests** bajo `restTests`; nunca toca el código de la aplicación ni añade dependencias.
- **Convención obligatoria**: cada `@Test` (y cada clase/`@Nested`) lleva un `@DisplayName` explícito en español, descriptivo y funcional. Está prohibida la generación automática de nombres (`@DisplayNameGeneration`, `ReplaceUnderscores`). Ese `@DisplayName` es exactamente lo que el ETP Excel exporta como **«Objetivo Funcionalidad»**.
- **Validación del contrato**: antes de persistir cada fichero, el servidor comprueba `@DisplayName` explícito en todos los tests, ausencia de `@Disabled`/`TODO`, uso real de Rest-Assured/JUnit 5 y cobertura de cada código de estado; si falla, reintenta la generación con el diagnóstico (`maxIterations`, 3 por defecto).
- **Ejecución iterativa hasta verde**: cumplido el contrato estático, el servidor **ejecuta la clase** contra el backend (wrapper `mvnw`/`gradlew` detectado, o `restRunCommand`), lee el **informe JUnit XML** de Surefire/Failsafe/Gradle y persiste el estado de **cada método `@Test`**. Si algo falla, reinyecta al modelo la salida real (errores de compilación y detalle de los tests en rojo) y vuelve a generar, hasta verde o agotar `maxIterations`. Una clase sólo queda **verde** si cumple el contrato **y** todos sus `@Test` pasan; un build que no ejecuta ningún test nunca cuenta como verde.
- **Reactores multi-módulo**: Surefire/Gradle escriben el informe en `<módulo>/target/surefire-reports`, no en la raíz del proyecto. El servidor **busca el XML en todo el árbol** (raíz y submódulos, en anchura) y se queda con el más reciente posterior al arranque de la ejecución. Sin esto, un build multi-módulo con todos sus tests en verde se leería como «no ejecutado» y la clase nunca podría ponerse verde. También se contempla que la clase esté en el **paquete por defecto**, en cuyo caso el XML se llama `TEST-<Clase>.xml` sin prefijo de paquete.
- **Estado persistido**: `restTests/.qa-mcp-rest-status.json` guarda por clase `green`, `contractVersion`, `attempts`, `validationErrors`, `totals` y la lista de `tests` con `passed`/`skipped` y la causa del fallo. Las clases ya verdes se **omiten** en llamadas posteriores (`skipGreen: false` para forzar su regeneración).
- **Log por clase**: `restTests/<Clase>.log`, sobrescrito en cada iteración, con el comando lanzado, el resultado por test, la **salida completa del build sin truncar**, el resumen inyectado al modelo y el prompt de corrección. Permite distinguir si el problema está en la ejecución real o en el prompt.
- **Build bloqueado por otra clase que no compila**: Maven/Gradle compilan **todo** `src/test/java` antes de aplicar el filtro `-Dtest=`, así que un `*ApiTest.java` roto impide ejecutar a **todas** las demás clases. El servidor atribuye cada error de compilación a su fichero y, si el culpable es otro test bajo `restTests`, **lo repara** (con sampling, reescribiéndolo hasta `maxCompileRepairRounds`, 3 por defecto; sin sampling, devolviendo sus errores y un **PROMPT DE REPARACIÓN por fichero**) en vez de quemar intentos reescribiendo la clase en curso, que no es la que rompe el build. La reparación debe conservar todos los `@Test` y `@DisplayName`: está prohibido borrar el fichero, comentar tests o marcarlos `@Disabled` para esquivar el error. Los errores de compilación del código de la aplicación **nunca** se tocan.
- **Verificadores de formato desactivados**: los tests generados son evidencias, no código de producto. Un `spotless:check` (o Checkstyle) enganchado al ciclo del build aborta **antes** de Surefire, así que la clase no llega a ejecutarse y jamás puede ponerse en verde por un salto de línea. El servidor añade `-Dspotless.check.skip=true -Dcheckstyle.skip=true` (Maven) o `-x spotlessCheck` (Gradle) a la invocación —también a un `restRunCommand` propio— sin modificar la configuración del proyecto. Si necesitas los ficheros formateados, ejecuta `mvn spotless:apply` aparte.
- **Fallos de entorno**: si el build no existe, no hay dependencias, el proxy corporativo devuelve **HTTP 407** o el backend está caído, se detecta como error de **ENTORNO**, se corta el bucle y se devuelve un diagnóstico accionable en vez de quemar intentos reescribiendo un test que no es el problema. Un error de compilación **nunca** se clasifica como fallo de entorno: lo provoca un `.java` generado por la tool y se arregla reescribiéndolo.
- **Proxy corporativo (HTTP 407)**: ante un `Proxy Authentication Required` al resolver dependencias, el servidor **reintenta automáticamente en modo offline** (`-o` / `--offline`) contra el repositorio local. Si aun así falla, indica cómo resolverlo: credenciales del proxy en `~/.m2/settings.xml`, variables `HTTP_PROXY`/`HTTPS_PROXY`/`NO_PROXY` (vía `restEnv`), o `restOffline: true` si `~/.m2` ya tiene las dependencias.
- **Parámetros**: `tags` (limita a uno o varios grupos de endpoints), `promptOverride`, `maxIterations`, `assisted`, `validateOnly`, `runTests` (`false` genera y valida sin ejecutar), `runTimeoutMs`, `skipGreen` y `maxCompileRepairRounds`.
- **Sin sampling** (Roo Code, Cline, opencode…): devuelve el prompt completo, las rutas exactas de los ficheros y el índice del código de backend para que el agente los abra y escriba los tests **sólo de las clases que aún no están en verde**; después debe llamar a `runRestTests` para ejecutarlas e iterar corrección→ejecución hasta que todas pasen.

### Bucle de auto-corrección REST (`runRestTests`)

Equivalente a `runE2ETests` para la capa API: aunque el cliente no tenga sampling, el servidor **sí puede ejecutar los tests** y devolver el resultado como feedback. Trabaja **una clase en curso cada vez** (la primera que no está en verde) y no avanza hasta que pasa:

1. `generateRestTests` → escribe los `*ApiTest.java` pendientes en sus rutas exactas.
2. `runRestTests` → el servidor ejecuta esa clase, persiste `green` y el estado de cada `@Test` en `.qa-mcp-rest-status.json`, y escribe su `.log`. Si pasa, indica avanzar; si falla, devuelve la **salida real del build** + un **PROMPT DE CORRECCIÓN**.
3. El agente reescribe el fichero y **vuelve a llamar** a `runRestTests` (misma clase) hasta que pase.

Si el build **ni siquiera compila** por culpa de otras clases de test, `runRestTests` no pide corregir la clase en curso: lista los ficheros que no compilan con sus errores (`- [línea,columna] mensaje`) y entrega un **PROMPT DE REPARACIÓN por fichero**, con la orden de repararlos y volver a llamar. Así el bucle nunca se queda atascado corrigiendo una clase que no es la culpable.

Cada respuesta termina con una `SIGUIENTE_ACCIÓN_OBLIGATORIA` concreta para que el agente no dé por cerrado el bucle tras un solo intento. Como todo el estado vive en **disco**, el ciclo es reanudable desde una tarea nueva con contexto limpio: el servidor reengancha la primera clase no verde.

Parámetros de `runRestTests`: `tags`, `promptOverride`, `runTimeoutMs`, `allFixes` (ejecuta todas las clases pendientes en vez de parar en la primera que falla) y `skipGreen`.

Ajustes opcionales de ejecución en `mcp.config.json`: `backend.mvn.path` y `backend.java.path` (Maven y JDK concretos, ver abajo), `restRunCommand` (comando base si no vale el wrapper detectado), `restEnv` (variables de entorno, p. ej. `HTTP_PROXY`/`NO_PROXY`), `restTimeoutMs` (timeout por clase, 15 min por defecto) y `restOffline` (`true` fuerza `-o`/`--offline` desde el primer intento; útil detrás de un proxy que exige autenticación).

### Maven y JDK a usar (`backend.mvn.path` / `backend.java.path`)

Cuando el Maven o el Java del `PATH` no son los correctos (varias versiones instaladas, Maven corporativo con su `settings.xml` y proxy ya configurados), se declaran explícitamente en `mcp.config.json`:

```json
"backend": {
  "root": "./backend",
  "language": "java",
  "build": "maven",
  "mvn": { "path": "C:\\apache-maven-3.9.6" },
  "java": { "path": "C:\\Program Files\\Java\\jdk-17" }
}
```

- `backend.mvn.path`: admite el **ejecutable** (`...\bin\mvn.cmd`), su carpeta `bin` o el **directorio de instalación**. Tiene prioridad sobre el wrapper `mvnw` del repositorio y sobre el `mvn` del `PATH`.
- `backend.java.path`: admite el **home del JDK**, su carpeta `bin` o el ejecutable `java`. Se exporta como `JAVA_HOME` y su `bin` se antepone al `PATH` de la ejecución.
- Ambas pueden ser **relativas a `mcp.config.json`**. Si la ruta no existe o no contiene el binario esperado, se reporta como fallo de **ENTORNO** con el motivo concreto, sin reescribir ningún test.

Para `generateE2ETests`, la generación es **genérica y guiada por LLM** (MCP sampling): para cada CU, el modelo del cliente genera un spec Cypress **real** (con `cy.intercept`, interacción con selectores derivados del código frontend y aserciones), no un esqueleto de `cy.log`. **Cada CU se genera en su propio fichero `.cy.js`** (un `describe` del RF con un único `it` del CU), de modo que cada ejecución de Cypress corre solo ese CU y el bucle itera más rápido y de forma aislada. Antes de empezar, la tool consulta `.qa-mcp-e2e-status.json`: conserva y omite los CU cuyo spec existe, tiene `green: true` y fue validado con la versión actual del contrato E2E; genera los specs que faltan y ejecuta/repara los existentes que aún no están en verde. Si cambia un contrato incompatible (por ejemplo, la forma segura de escribir inputs), los verdes antiguos se revocan y se regeneran una sola vez.
- Puedes definir las reglas de estilo/interacción con `prompts.e2e` en `mcp.config.json` (opcional). Si no se indica, usa `prompts/e2e.md` del servidor MCP.
- También puedes pasar `promptOverride` en la invocación de la tool para ajustar una ejecución puntual.
- Requiere un cliente MCP que soporte sampling (p. ej. VS Code Copilot 1.102+). Si el cliente **no** soporta sampling (Roo Code, Cline, opencode…), la tool pasa a **modo asistido** (ver más abajo).

**Modo asistido (sin MCP sampling):** si el cliente conectado no declara la capacidad `sampling`, `generateE2ETests` y `autoCompleteRfCu` **no pueden pedir la generación al modelo por sí mismas**. En su lugar:
- `generateE2ETests` prepara el entorno Cypress (helpers, config y baseline) y trabaja con **UN CU no verde por llamada**. Si su spec no existe, devuelve el prompt de generación y la ruta de salida exacta; si ya existe, indica que debe ejecutarse con `runE2ETests` para validarlo o repararlo. En vez de embeber el código frontend (que desborda el contexto del cliente), el prompt **lista las rutas de los ficheros relevantes** para que el agente los abra con sus propias herramientas de fichero.
- `autoCompleteRfCu` **devuelve el prompt** y la ruta de salida para que el agente genere y escriba `rf-cu.md`.
- El modo asistido se activa **automáticamente** al detectar la falta de sampling. También puedes forzarlo con el parámetro `assisted: true` en la invocación.

> **Decenas de CU sin llamadas ni prompts manuales:** sin MCP sampling, el servidor no puede generar por sí solo el contenido de los specs, por lo que técnicamente el flujo necesita varias llamadas MCP (`generateE2ETests` → escribir spec → `runE2ETests` → corregir/volver a ejecutar → siguiente CU). El usuario, sin embargo, **solo tiene que invocar `generateE2ETests` una vez**. La descripción de la tool y todas sus respuestas asistidas ya incorporan un **MANDATO DE AUTOCONTINUACIÓN** para que el agente escriba/corrija los specs y encadene las llamadas necesarias sin pedir confirmación ni detenerse entre CU. `.qa-mcp-e2e-status.json` conserva el progreso. Si el cliente no puede encadenar tools, será necesario usar un orquestador; esa es una limitación del cliente, no hace falta suplirla con un prompt del usuario.

Invocación inicial en modo asistido (también se activa automáticamente cuando no hay sampling):

```json
{
  "assisted": true
}
```

**Bucle de auto-corrección en modo asistido (`runE2ETests`), CU a CU hasta verde:** aunque el cliente no tenga sampling, el servidor **sí puede ejecutar Cypress** y devolver el resultado como feedback. El flujo trabaja **un CU en curso cada vez** (el primero que no está en verde) y **no avanza al siguiente hasta que el actual pasa**:
1. `generateE2ETests` (modo asistido) → devuelve el prompt de generación del **CU en curso** (si su `.cy.js` no existe). El agente lo escribe.
2. `runE2ETests` → el servidor **ejecuta SOLO ese CU** (limpiando el baseline entre intentos). Si pasa, lo **marca en verde** (estado persistido en disco) y te indica avanzar; si falla, devuelve la **salida real de Cypress** + un **PROMPT DE CORRECCIÓN**.
3. El agente aplica el prompt reescribiendo el fichero y **vuelve a llamar** a `runE2ETests` (mismo CU) hasta que pase.
4. Con el CU en verde, se llama de nuevo a `generateE2ETests` para el **siguiente** CU. Repetir hasta que todos estén en verde.

**Contexto limpio por CU:** todo el estado vive en **disco** (los `.cy.js` + `.qa-mcp-e2e-status.json` con los CU en verde), no en la conversación del cliente. Por eso el bucle es reanudable: si el cliente admite subtasks, el mandato integrado le indica que delegue automáticamente el siguiente CU con contexto limpio; si no, continúa en la tarea actual. El usuario no tiene que iniciar otra tarea ni repetir la instrucción. El servidor detecta el siguiente CU pendiente automáticamente y cada llamada emite solo el CU en curso (frontend como lista de rutas, no código embebido) para minimizar el footprint.

**Automatizar el contexto limpio con subtasks (Roo Code / Orchestrator):** en clientes con orquestación de subtasks (Boomerang / Orchestrator, p. ej. **Roo Code**), no hace falta iniciar la tarea nueva a mano. Cada respuesta de `generateE2ETests` / `runE2ETests` incluye una **`SEÑAL DE SUBTASK`** con un campo `QUEDA_TRABAJO` (sí/no) y la instrucción de si seguir en el mismo subtask o delegar el siguiente paso en un `new_task` con contexto limpio. Como todo el estado está en disco, cada subtask arranca limpio y el servidor resuelve solo el CU pendiente.

> **Higiene de contexto en el bucle de corrección:** el contexto se llena sobre todo al **iterar correcciones dentro de un mismo CU** (cada vuelta reinyecta spec + salida de Cypress + reglas, y el agente reescribe el fichero entero). Por eso se delega **un subtask por CU** (contexto limpio para cada CU), y **dentro** de ese subtask el agente itera corrección→`runE2ETests` hasta que ESE CU pase. Si aun así el contexto de un CU muy largo se llena, hay un **offload OPCIONAL**: cierra la tarea y deja que una tarea/subtask NUEVA reanude EL MISMO CU (el `.cy.js` y el estado quedan en disco; el servidor reengancha el primer CU no verde). El offload es un alivio puntual, **no** un fin del bucle: nunca cierres un CU en rojo dándolo por terminado.

> **IMPORTANTE — modos de Roo y acceso MCP:** el modo **Orchestrator NO tiene acceso directo a tools MCP** (solo delega vía `new_task`); si le pides que llame a `autoCompleteRfCu`/`generateE2ETests` directamente, responderá que *"no es una tool reconocida"*. La llamada a la tool debe ocurrir **dentro del subtask**, en un modo con el grupo `mcp` **y** `edit`. Usa **modo Code** (`mode: "code"`) para los subtasks: como Roo no soporta sampling, las tools corren en modo asistido y el agente debe **escribir** los ficheros (`rf-cu.md`, `.cy.js`), así que hace falta editar. (Architect solo edita markdown; Ask no edita.)

Prompt listo para pegar en la **tarea padre** (Roo en modo Orchestrator):

```
Eres el orquestador del bucle E2E de qa-mcp. Objetivo: dejar TODOS los CU en verde.
Delega UN subtask por CU (contexto limpio por CU); el estado vive en disco y el
servidor reengancha el CU pendiente en cada subtask.

Repite este ciclo:
1. Crea un new_task EN MODO CODE (mode: "code") con contexto limpio y este objetivo
   (el modo Code es obligatorio: tiene acceso a las tools MCP y puede escribir ficheros;
   tú, como Orchestrator, NO puedes llamar a las tools qa-mcp directamente):
   "Deja EN VERDE el CU pendiente de qa-mcp (se resuelve solo desde disco):
    - Si no tiene spec: llama a generateE2ETests, escribe el .cy.js en la ruta EXACTA
      indicada y llama a runE2ETests.
    - Si ya tiene spec: llama a runE2ETests.
    Si FALLA, aplica el PROMPT DE CORRECCIÓN (reescribe el .cy.js completo) y VUELVE A
    LLAMAR a runE2ETests. Repite corrección→runE2ETests hasta que ESTE CU pase. NO cierres
    la tarea con el CU en rojo. (Solo si el contexto se te llena, puedes cerrar y dejar
    que otra tarea reanude ESTE MISMO CU desde disco.) Cuando pase, termina con
    attempt_completion indicando 'CU en verde' y copia la línea QUEDA_TRABAJO de la
    SEÑAL DE SUBTASK."
2. Cuando el subtask termine, lee su resultado (la línea QUEDA_TRABAJO).
3. Si QUEDA_TRABAJO: sí (siguiente CU), vuelve al paso 1.
4. Si QUEDA_TRABAJO: no (TODOS los CU en verde), termina.

No generes ni ejecutes tests tú mismo: delega SIEMPRE cada CU en un subtask en modo
Code con contexto limpio.
```

En clientes CON sampling no hace falta ni el bucle manual ni los subtasks: `generateE2ETests` reanuda el estado de `.qa-mcp-e2e-status.json`, genera lo que falta y ejecuta/repara los CU no verdes por sí misma.

**Ejecución iterativa (auto-fix):** por defecto, `generateE2ETests` **ejecuta Cypress** sobre cada CU pendiente. Si el spec no existe, primero lo genera; si ya existe, no está verde y cumple el contrato actual, lo conserva y lo ejecuta directamente. Si usa una interacción de input insegura o le faltan evidencias, primero solicita su reparación al modelo. Cuando Cypress falla, pide al modelo que **corrija el spec usando la salida de error real**, repitiendo hasta que pase o se agoten los intentos. Cada resultado se persiste como `green: true/false` y `contractVersion` en `.qa-mcp-e2e-status.json`. Parámetros de la tool:
- `runTests` (bool, por defecto `true`): ejecuta Cypress e itera. Ponlo a `false` para solo generar.
- `maxIterations` (número, por defecto `3`): intentos máximos por CU (1 generación + N-1 correcciones).
- `rf` (string, opcional): limita estrictamente todo el ciclo a un único RF, p. ej. `"RF-3"`. Es la opción recomendada para ejecutar una tarea/contexto independiente por RF.
- `rfFilter` (array de ids, opcional): compatibilidad para limitar a varios RF, p. ej. `["RF-01","RF-03"]`. No se combina con `rf`.
- `promptOverride` (string, opcional).
Entre cada intento se limpian las claves de baseline del CU en curso para que la re-ejecución vuelva a autocapturar. El contrato v2 separa acciones humanas y operaciones técnicas: una acción humana puede agrupar varios controles relacionados, pero Cypress ejecuta y captura cada operación de forma independiente (`rf1_cu1_01.png`, `rf1_cu1_02.png`, etc.). Si Cypress reintenta un test, el MCP reconoce `(attempt N)`, exige que el último intento tenga el juego completo y normaliza los nombres sin mezclar intentos. Todas las evidencias deben medir **1920×1080** con DPR **1 (100 %)**. Los `set-control` usan `setDocumentedControl`, que aplica el dato exacto, espera re-renderizados, resuelve controles nativos, centra el elemento, comprueba oclusiones, verifica el estado visible y captura el PNG. Las demás operaciones usan `cy.screenshot()` tras completarse. Un CU sólo queda verde con spec vigente, contrato coherente, baseline correcto y todas sus evidencias Full HD.

### Un contexto por RF

Para generar únicamente los tests de un requisito funcional:

```json
{
  "rf": "RF-3"
}
```

La tool sólo considera los CU de `RF-3`: no genera, ejecuta, repara ni cambia el estado de otros RF. En modo asistido, todas las respuestas incorporan el mismo argumento en las llamadas posteriores (`runE2ETests({ "rf": "RF-3" })` y `generateE2ETests({ "rf": "RF-3" })`) y ordenan continuar en la misma tarea mientras quede algún CU de ese RF en rojo. Cada respuesta termina además con una `SIGUIENTE_ACCIÓN_OBLIGATORIA` concreta para evitar que el agente dé por finalizado el bucle después de una sola ejecución. Sólo cuando todos sus CU están verdes, la respuesta termina el ámbito y ordena no saltar a otro RF. Se puede entonces abrir una tarea o contexto nuevo e invocar la tool con el siguiente RF; el progreso anterior se recupera desde disco.

## Exportación del ETP a Excel

`exportETPAsExcel` genera un libro con la misma tabla y estilos de la plantilla configurada en `evidence.excelTemplate`. Si esa ruta no existe en el proyecto consumidor, usa automáticamente el `templates/evidences.xlsx` empaquetado con `qa-mcp`. Las filas de ejemplo que contenga la plantilla se eliminan y se sustituyen por los tests reales disponibles:

- una fila `REST-NNN` por cada método Java anotado con `@Test` encontrado bajo `restTests`;
- una fila `E2E-NNN` por cada `it()` o `test()` encontrado en los `.cy.js` bajo `e2eTests`;
- RF, CU, objetivo y acciones se obtienen de `rf-cu.md` cuando el test puede relacionarse con él; en las filas `REST`, el «Objetivo Funcionalidad» es el `@DisplayName` literal del método `@Test`;
- las filas muestran primero todos los casos `REST` y después todos los `E2E`; dentro de cada bloque se ordenan por `R. Funcional` y luego por `Nombre` (CU), usando orden natural para los identificadores numéricos;
- los E2E usan `.qa-mcp-e2e-status.json` y su `.log` para mostrar `OK`, `KO`, `PASS` o `FAIL`;
- los Rest Assured usan `.qa-mcp-rest-status.json` y su `.log` para mostrar `OK`, `KO` u `OMITIDO`; si la clase aún no se ha ejecutado, aparecen como `NO EJECUTADO`;
- `it.skip` y `@Disabled` se muestran como `OMITIDO`.

La tool acepta opcionalmente `outputFileName`; si no se indica, escribe `ETP.xlsx` dentro de `evidence.output`. Funciona si solo existen tests REST, solo E2E o ambos. No ejecuta los tests durante la exportación: refleja los resultados persistidos que estén disponibles. Si no encuentra ningún `@Test`, `it()` o `test()`, devuelve un error claro en vez de crear un ETP vacío.

## Informe de evidencias Rest Assured (`exportRestTestsAsExcel`)

`exportRestTestsAsExcel` genera un informe Excel **exclusivo de los tests REST** generados previamente con `generateRestTests`, reutilizando la misma tabla y estilos de `evidence.excelTemplate` (o del `templates/evidences.xlsx` empaquetado). Escribe una fila `REST-NNN` por **cada método `@Test`** encontrado bajo `restTests`:

- `R. Funcional`, `Nombre` y `Objetivo Funcionalidad`: el `@DisplayName` literal del método (si falta, se humaniza el nombre Java);
- `Aplicacion`: el proyecto derivado de `backend.root`, con el sufijo `BACKEND`;
- `Requisitos Previos / Restricciones`: `Entorno: <DES|PRE|PRO|INT|LOCAL> | Inicio: <fecha de ejecución>`; el entorno se deriva del host realmente invocado (o del `servers` de OpenAPI) y la hora de inicio, del informe de ejecución;
- `Acciones`: la petición real, con el formato `GET <url> => <código>`. Si hay log de Rest Assured en el informe se usa la URI y el status reales; si no, se reconstruyen desde el propio test (`get/post/...`, `queryParam`, `pathParam`, constantes `String` de la clase y `statusCode(...)`);
- `Resultado`: `OK`, `KO`, `OMITIDO` (`@Disabled`/`skipped`) o `NO EJECUTADO`;
- `Resultado reproducido`: `PASS | ...`, `FAIL | ... | <mensaje del fallo>`, `SKIPPED | ...` o `PENDIENTE | <fichero>#<método>`.

Los resultados provienen de **una ejecución local previa**: la tool **no ejecuta los tests**, sólo lee los informes JUnit ya existentes (`surefire-reports`, `failsafe-reports` o `build/test-results/**`) bajo `backend.root`, quedándose con la ejecución más reciente de cada método. Si no encuentra ningún informe, exporta igualmente el inventario completo con todos los casos como `NO EJECUTADO` y lo advierte en la respuesta.

Detalles que evitan informes incompletos o engañosos:

- **Sólo las clases generadas**: `restTests` suele ser el `src/test/java` del módulo, compartido con los tests unitarios escritos a mano. El informe se limita a las clases registradas en `.qa-mcp-rest-status.json`, de modo que no se cuelan tests ajenos (que además aparecerían con nombres en inglés, sin `@DisplayName` en castellano).
- **Anotaciones multilínea**: el formateador (google-java-format/Spotless) parte los `@DisplayName` largos en varias líneas. El parseo recorre las anotaciones con paréntesis equilibrados en vez de con un patrón de una línea, así que no se pierde ningún `@Test`.
- **Clases `@Nested`**: Surefire escribe en `classname` el `@DisplayName` del grupo (p. ej. `GET /destinations`), no el nombre Java. El emparejamiento usa el nombre de la **suite**, que sí es la clase de nivel superior; si no, todos los tests anidados saldrían como `NO EJECUTADO` pese a haberse ejecutado.
- **URL base parametrizada**: los tests generados usan `System.getProperty("api.base.uri", "https://…")`. Se resuelve el valor por defecto y se respeta que la ruta ya sea absoluta; sin ello, la columna `Acciones` mostraría «petición no deducible del test» en casi todas las filas.

Parámetros (todos opcionales):

| Parámetro | Descripción |
|---|---|
| `outputFileName` | Nombre del fichero dentro de `evidence.output`. Por defecto `restassured-evidences.xlsx`. |
| `outputPath` | Ruta completa (absoluta o relativa a `mcp.config.json`). Tiene prioridad sobre `outputFileName`. |
| `baseUri` | URL base para reconstruir las peticiones de los tests sin log de ejecución. Por defecto, el `servers` de OpenAPI. |

```json
{
  "outputPath": "C:/Users/usuario/Downloads/restassured-evidences.xlsx"
}
```

Si no existe ningún método `@Test` bajo `restTests`, devuelve un error claro en vez de generar un informe vacío.

## Exportación del ETP a Word

`exportETPAsWord` construye el documento a partir de `rf-cu.md`: crea un encabezado de nivel 1 por cada RF y, dentro de él, un encabezado de nivel 2 por cada CU. Sólo muestra las acciones para ejecución manual; nunca exporta componentes, selectores ni instrucciones Cypress. Bajo cada acción agrupa uno o varios PNG (`rfx_cuy_NN.png`), uno por operación técnica. Los RF, CU y acciones siguen orden natural.

El Word sólo se exporta si todos los CU están en verde y existe una captura PNG válida por cada operación. Si falta alguna evidencia, la tool devuelve un error con los CU y ficheros pendientes en vez de generar un documento incompleto. Ejecuta antes `generateE2ETests` hasta completar el conjunto.

Para `autoCompleteRfCu`, la generación es **genérica y guiada por LLM** (no usa plantillas ni heurísticas de dominio) y es **UI-first**: los RF/CU describen **lo que el usuario puede reproducir DESDE LA UI**, no la API completa.
- **Con `frontend.root` configurado (modo UI-first):** los **RF** se derivan de lo que la UI expone (rutas de `appRouting`, componentes/pantallas y acciones que el usuario puede disparar) y los **CU** son los flujos concretos ejercitables desde la interfaz. OpenAPI se usa **solo como referencia** para entender el comportamiento, **no** como checklist de cobertura: no se crea un RF por endpoint ni se prueban casos que la UI no permite. La cobertura exhaustiva de la API es tarea de `generateRestTests`.
- **Sin `frontend.root` (modo fallback OpenAPI-first):** `frontend.root` es **opcional**; si no se define, no hay UI que analizar y los **RF se infieren directamente de los endpoints de OpenAPI** (un RF por operación/funcionalidad relevante), con CU a nivel de comportamiento esperado del endpoint.
- Los **CU** los **estima el modelo del cliente** analizando el código frontend real (componentes, plantillas, servicios), vía **MCP sampling** (`sampling/createMessage`).
- Requiere un cliente MCP que soporte sampling (p. ej. VS Code Copilot 1.102+). Sin sampling, la tool devuelve el prompt para que el agente del cliente genere y escriba `rf-cu.md`; después debe llamar a `autoCompleteRfCu` con `validateOnly: true` y corregir el documento hasta que el servidor lo acepte.
- El prompt de instrucciones está externalizado en `prompts/rfcu.md` (configurable con `prompts.rfcu` en `mcp.config.json`, opcional). Si no se indica, usa el `prompts/rfcu.md` del servidor MCP.
- Si ya existe un `rf-cu.md` parcial, se completa respetando lo ya definido.
- Cada CU contiene dos proyecciones enlazadas: `Acciones para ejecución manual`, que alimenta Excel/Word y no expone selectores ni Cypress, y un `Contrato de automatización` estructurado que alimenta los tests. Una acción humana puede agrupar varias operaciones, pero cada operación conserva su selector, valor y evidencia independiente:
- Toda acción manual indica el valor literal de cada campo: fecha, hora, número, texto y texto visible exacto de cada dropdown. Expresiones como «una opción disponible», «un valor válido» o «indicar la fecha y la hora» se rechazan. Datepicker, timepicker y textarea se registran técnicamente como `input`; `set-control` sólo admite `input`, `select` y `checkbox`.
- El servidor extrae un inventario compacto de controles de todas las plantillas Angular y valida la cadena `frontend → contrato técnico → acción humana`. Un CU que pulse una acción de cálculo/consulta no puede omitir silenciosamente fecha, hora u otro control de su componente. En modo sampling se realizan hasta tres intentos de autocorrección antes de rechazar el documento.

```markdown
- **CU-1: Cálculo nominal.**
  - **Acciones para ejecución manual:**
  1. Acceder al Simulador de facturas.
  2. Seleccionar «Org. Ventas de AASA» en Sociedad e introducir 180000 en Peso de la aeronave.
  3. Comprobar que Importe total muestra el importe calculado.
  - **Contrato de automatización:**
    - `A01.1` | acción `01` | operación `visit` | etiqueta `Simulador de facturas` | destino `/simulador-de-facturas`
    - `A02.1` | acción `02` | operación `set-control` | clave `sociedad` | tipo `select` | etiqueta `Sociedad` | selector `#sociedad` | valor `Org. Ventas de AASA`
    - `A02.2` | acción `02` | operación `set-control` | clave `pesoAeronave` | tipo `input` | etiqueta `Peso de la aeronave` | selector `#pesoAeronave input` | valor `180000`
    - `A03.1` | acción `03` | operación `verify` | etiqueta `Importe total` | selector `#importeTotal` | resultado `muestra el importe calculado`
```

Los documentos v1 siguen siendo legibles durante la migración, pero `autoCompleteRfCu` genera exclusivamente el contrato v2. Los CU verdes anteriores se revalidan porque cambia la relación entre acciones y evidencias.

La generación E2E incluye baseline autocapturable de snapshots genéricos (API/UI):
- asegura Cypress en el frontend (`devDependencies.cypress`) y scripts `e2e` / `e2e:open`
- asegura `cypress.config.js` y registra `registerBaselineTasks(on)` en `setupNodeEvents` (omite la inyección si tu config ya define las tareas `readBaseline`/`writeBaseline`, para no duplicarlas)
- usa `e2eBaseUrl` de `mcp.config.json` para `cy.visit(...)` en los specs generados
- crea `cypress/support/e2e-baseline.js`
- crea `cypress/fixtures/e2e-baseline.json`; si detecta snapshots contaminados con `[object Event]`, elimina sólo esas entradas, revoca el verde de sus CU y las vuelve a capturar en la siguiente ejecución
- crea `cypress/support/baseline-tasks.js` con tareas `readBaseline` y `writeBaseline`
- crea `cypress/support/e2e-helpers.js`: librería compartida que incluye `setDocumentedControl(clave, tipo, selector, valor, captura)`. Para `input` usa el setter nativo y eventos de la ventana AUT, evitando `[object Event]`; para `select` elige y verifica el texto visible exacto aunque Angular use `[ngValue]`; para `checkbox` establece y verifica `true`/`false`. En los tres casos vuelve a resolver el DOM tras el cambio, lleva el control al viewport, lo resalta, genera el PNG y registra el dato bajo `inputs` para compararlo con `rf-cu.md`.

Antes de lanzar Cypress, es necesario ejecutar:

`set NO_PROXY=localhost,127.0.0.1,.aena.es`

Además, en la configuración de proxy del sistema, la IP/host del proxy debe ser:

`proxym.aena.es`

sin incluir `http://`.

En `cypress.config.js`, registra esas tareas desde `setupNodeEvents(on)`:
`const { registerBaselineTasks } = require('./cypress/support/baseline-tasks'); registerBaselineTasks(on);`

## Configuración en VS Code Copilot (MCP)

Configuración recomendada: por proyecto, en `.vscode/mcp.json` (no en configuración global de usuario).

En la raíz del proyecto que quieres documentar, crea `.vscode/mcp.json` con:

```json
{
    "servers": {
        "qa-mcp": {
            "type": "stdio",
            "command": "C:\\Program Files\\nodejs\\node.exe",
            "args": ["C:\\EnvAena\\workspace\\qa-mcp\\dist\\index.js"],
            "cwd": "${workspaceFolder}"
        }
    }
}
```

Y elimina `qa-mcp` de la configuración global (**MCP: Open User Configuration**) para evitar conflictos entre proyectos.

## Uso en un proyecto (guía rápida)

1. En el proyecto a documentar, crea/ajusta `mcp.config.json` en su raíz con rutas de backend, frontend, OpenAPI y salidas de tests/evidencias.
   - Para fijar el Maven y el JDK con los que se ejecutan los tests REST, añade `backend.mvn.path` y `backend.java.path` (ejecutable o directorio de instalación).
   - Si quieres controlar explícitamente de dónde derivar CU, añade `appRouting` con la ruta del `app-routing.module.ts`.
   - Para fijar la URL de ejecución E2E, añade `e2eBaseUrl` (ej. `https://mi-entorno.aena.es`).
   - Para ejecutar Cypress con un Node concreto (p. ej. instalación nvm), añade `e2eNodePath` con el directorio que contiene `node.exe`/`npx` (por defecto `C:\Users\aena\AppData\Roaming\nvm\v24.16.0`); se antepone al `PATH` de la ejecución de Cypress.
   - Para pasar variables de entorno a la ejecución de Cypress (proxy, etc.), añade `e2eEnv` como objeto clave/valor. Por defecto se establece `NO_PROXY=localhost,127.0.0.1,.aena.es`; puedes sobreescribirlo o añadir más variables. Ej.: `"e2eEnv": { "NO_PROXY": "localhost,127.0.0.1,.aena.es", "HTTP_PROXY": "" }`.
   - Para **ver el navegador mientras Cypress ejecuta** (modo headed), añade `"e2eHeaded": true`: el runner del MCP añade `--headed`, así que ves cada spec en un navegador visible (se cierra al terminar; NO se usa `--no-exit` para no colgar la llamada MCP). Opcionalmente `"e2eBrowser": "chrome"` (o `edge`/`firefox`/`electron`) para elegir navegador — debe estar instalado; por defecto Electron.

   > **⚠️ Timeout MCP en Roo/Cline (`MCP error -32001: Request timed out`):** una corrida real de Cypress (arranque + navegador + tests) supera con facilidad el **timeout por defecto de 60 s** de las llamadas MCP. Sube el `timeout` del servidor `qa-mcp` en la config MCP del cliente (Roo permite hasta 3600 s; recomendado **600**). Es imprescindible además si la tool tiene que **reparar la caché de Cypress** (descarga del binario, ver abajo).

   > **⚠️ `Invalid or incompatible cached data (cachedDataRejected)` al lanzar Cypress:** es un **error de ENTORNO** (caché V8 del binario de Cypress corrupta/incompatible con la versión de Node), **no** del spec. `runE2ETests`/`generateE2ETests` lo **detectan y reparan automáticamente una vez** (`cypress cache clear` + `install` + `verify`) y reintentan; si persiste, devuelven un aviso claro (NO reescriben el test). Repara manualmente en el frontend, con el Node configurado en el PATH: `npx cypress cache clear && npx cypress install && npx cypress verify`. La reparación descarga el binario: asegura conectividad a `download.cypress.io` (revisa `NO_PROXY`) y **sube el timeout MCP** (arriba).

2. En VS Code Copilot, configura y arranca el servidor MCP `qa-mcp` con `cwd` apuntando a ese proyecto.
3. En Copilot Chat (modo Agent), ejecuta las tools según necesidad:
   - `autoCompleteRfCu`: completa `rf-cu.md`. Infiere RF desde OpenAPI + `appRouting` y estima los CU con el LLM del cliente (MCP sampling) analizando el frontend.
   - `generateRestTests`: genera tests de integración de API (Java + JUnit 5 + Rest-Assured) desde OpenAPI + código de backend, los ejecuta y persiste su estado por test.
   - `runRestTests`: ejecuta los tests REST ya escritos y devuelve el prompt de corrección para iterar hasta verde.
   - `generateE2ETests`: genera tests E2E (Cypress) y deja Cypress/baseline configurado en frontend.
   - `exportETPAsExcel` / `exportETPAsWord`: exportan el plan de pruebas con evidencias.
   - `exportRestTestsAsExcel`: exporta el informe de evidencias de los tests Rest Assured con el resultado de la última ejecución local.
4. Revisa los artefactos generados en:
   - tests API: ruta configurada en `restTests`
   - tests E2E: ruta configurada en `e2eTests`
   - evidencias: carpeta configurada en `evidence.output`

Nota: las tools usan siempre `mcp.config.json` desde la raíz del proyecto en el que se ejecuta el MCP (`cwd`).

TDQS

C2.8/5.0

Scored across 5 tools

Disambiguation4/5

The tools are mostly distinct: autoCompleteRfCu for document completion, exports to two formats (Excel/Word), and two test generators (E2E/API). The export pair could be confused by name alone, but descriptions clarify the format difference.

Naming Consistency5/5

All tool names follow a consistent camelCase pattern with verb+object (autoComplete, export, generate). Abbreviations like RfCu, ETP, Excel, Word, E2E, Rest are used consistently. No mixing of styles.

Tool Count5/5

5 tools is well-scoped for a QA server covering document management, export, and test generation. Not too few or too many.

Completeness3/5

The tools cover test preparation and generation but lack execution, reporting, or defect management. Could be more complete for a QA server, but covers core generation tasks.

Maintenance

ActivityMaintained
ResponsivenessNo issues