clase:daw:daw-proyecto:tema06
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previa | |||
| clase:daw:daw-proyecto:tema06 [2026/10/14 13:10] – «Fábrica» pasa a «arnés» / ingeniería de arneses (harness engineering, dicho en el tema 1); el día de trabajo en impersonal, sin Lorenzo; ejemplos con <alumno> claude | clase:daw:daw-proyecto:tema06 [2026/10/14 14:08] (actual) – Tema nuevo «2. IA y agentes»: los temas 2 a 7 pasan a ser 3 a 8, con sus referencias cruzadas renumeradas claude | ||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| - | ====== 6. Despliegue en el proyecto ====== | + | ====== 6. Automatizando |
| - | Objetivo del tema: ''/ | + | Objetivo del tema: que la calidad la vigilen |
| - | Lo que ya sabéis: qué es GitHub Actions | + | Una skill nueva, ''/ |
| - | ===== El servidor ===== | + | ^ Skill ^ Sustantivos ^ Verbos ^ |
| + | | ''/ | ||
| + | | ''/ | ||
| - | Un VPS compartido por toda la clase, con tres cosas montadas por el profesor: | + | ===== Los cuatro tipos de tests ===== |
| - | * **Docker.** | + | ^ Tipo ^ Qué prueba ^ Con qué ^ Necesita ^ Lo ejecuta ^ |
| - | * **nginx-proxy** en la red '' | + | | '' |
| - | * **Un runner autoalojado | + | | '' |
| + | | '' | ||
| + | | '' | ||
| - | < | + | Los dos primeros forman parte del build de Maven: corren en cada compilación y no necesitan nada levantado. Los dos últimos **no forman parte del build**: son lentos, necesitan la aplicación |
| - | ===== Los mismos scripts | + | ===== Crear los tests: /test < |
| - | En el servidor no hay nada nuevo que aprender: la aplicación se opera con el **mismo script** del tema 3, '' | + | ==== arch: tests de arquitectura |
| - | < | + | Las reglas de arquitectura (las de Programación y DWS: capas, nombres, sin ciclos, '' |
| - | COMPOSE_FILE=compose.yaml | + | |
| + | < | ||
| + | /test arch create | ||
| + | - Las clases de controller solo dependen de domain. | ||
| + | - Las de persistence solo dependen de domain. | ||
| + | - Nada en domain importa org.springframework ni jakarta.persistence. | ||
| + | - Los controladores acaban en Controller y están en ..controller.. | ||
| + | - Los repositorios de persistence acaban en RepositoryImpl e implementan una interfaz de domain. | ||
| + | - Sin ciclos entre paquetes. | ||
| + | </ | ||
| + | |||
| + | Cada test lleva en su '' | ||
| + | |||
| + | < | ||
| + | @Test | ||
| + | @DisplayName(" | ||
| + | void domainSinSpring() { | ||
| + | noClasses().that().resideInAPackage(" | ||
| + | .should().dependOnClassesThat().resideInAPackage(" | ||
| + | .check(clases); | ||
| + | } | ||
| </ | </ | ||
| - | | + | **No hay un documento aparte con la arquitectura.** Mantener un Markdown sincronizado con los tests es un trabajo que nadie hace, así que la fuente |
| - | * '' | + | |
| - | * Los workflows solo llaman a '' | + | |
| - | ===== Secretos ===== | + | ==== unit: tests unitarios con JUnit ==== |
| - | La contraseña de la base de datos de producción no está en ningún fichero: está en //Settings → Secrets and variables → Actions// del repositorio como '' | + | Los tests unitarios prueban |
| - | ===== Los workflows ===== | + | < |
| + | /test unit create | ||
| + | </ | ||
| - | Un solo fichero para CI y CD: | + | Sin argumento genera los de todas las clases que no los tienen; con una clase o un paquete (''/ |
| - | <sxh yaml;title:.github/workflows/ci-cd.yml> | + | Lo que hace: lee la clase, identifica cada comportamiento (lo que devuelve, lo que valida, lo que lanza) y escribe un test por comportamiento en '' |
| - | name: CI/CD | + | |
| - | on: | + | Qué no prueban: controladores ni repositorios. Eso es de los tests de API. |
| - | push: | + | |
| - | branches: [develop, main] | + | |
| - | workflow_dispatch: | + | |
| - | jobs: | + | ==== api: tests de API con Playwright ==== |
| - | ci: | + | |
| - | runs-on: ubuntu-latest | + | |
| - | steps: | + | |
| - | - uses: actions/ | + | |
| - | - uses: actions/ | + | |
| - | with: { distribution: | + | |
| - | - uses: actions/ | + | |
| - | with: { node-version: | + | |
| - | - name: Levantar la aplicación | + | Los tests de API prueban cada endpoint **de verdad**: peticiones HTTP contra el backend del worktree, comprobando el código de estado y el JSON. Se escriben con Playwright, igual que los E2E (mismo lenguaje, misma configuración, |
| - | env: { DB_PASSWORD: | + | |
| - | run: | | + | |
| - | docker network create nginx-proxy-network | + | |
| - | docker compose up -d --build --wait | + | |
| - | - name: Tests del backend (unitarios y ArchUnit) | + | < |
| - | | + | /test api create Pedido: alta válida, sin cliente, cliente que no existe, borrar uno con líneas |
| - | run: mvn -B test | + | </ |
| - | - name: Tests de API y E2E | + | El argumento son los **escenarios**: qué hay que probar, en texto. Por cada uno, en '' |
| - | working-directory: frontend | + | |
| - | run: | | + | |
| - | npm ci | + | |
| - | npx playwright install --with-deps chromium | + | |
| - | npm run test:api | + | |
| - | npm run test:e2e | + | |
| - | deploy: | + | <sxh typescript> |
| - | | + | test(' |
| - | if: github.ref == 'refs/heads/main' | + | const res = await request.post('/api/pedidos', { data: { fecha: '2026-10-14', clienteId: 1 } }); |
| - | runs-on: self-hosted | + | |
| - | steps: | + | |
| - | | + | }); |
| - | | + | |
| - | env: | + | |
| - | COMPOSE_FILE: | + | |
| - | DB_PASSWORD: | + | |
| - | | + | |
| - | - name: Smoke test | + | |
| - | run: curl -fsS http://< | + | |
| </ | </ | ||
| - | Lo que hay que entender: | + | Los de API y los E2E son dos **proyectos** del mismo '' |
| + | |||
| + | <sxh typescript; | ||
| + | export default defineConfig({ | ||
| + | use: { baseURL: process.env.BASE_URL ?? ' | ||
| + | projects: [ | ||
| + | { name: ' | ||
| + | { name: ' | ||
| + | ], | ||
| + | }); | ||
| + | </ | ||
| + | |||
| + | ==== e2e: tests E2E con Playwright ==== | ||
| + | |||
| + | Los tests E2E prueban la aplicación completa desde el navegador, como lo haría el usuario. Los criterios de aceptación de '' | ||
| + | |||
| + | < | ||
| + | /test e2e create los criterios de aceptación de requirements.md | ||
| + | </ | ||
| + | |||
| + | Cómo trabaja: lee los criterios, abre la aplicación del worktree con el Playwright MCP para ver qué hay en pantalla, escribe el test y lo ejecuta; si falla por un selector o un texto, lo arregla y lo vuelve a pasar. La IA interviene **al generar**, no al ejecutar: lo que queda en el repositorio es un '' | ||
| + | |||
| + | Reglas que la skill tiene que respetar (están en '' | ||
| + | |||
| + | * Selectores por '' | ||
| + | * Un test por criterio de aceptación, | ||
| + | * Los tests cuentan con los datos de prueba del tema 4 y **se pasan sobre la base de datos recién reseteada**. | ||
| + | |||
| + | ===== Ejecutarlos: | ||
| + | |||
| + | Ejecuta los tests de un tipo y, si algo sale en rojo, lo explica: qué test, qué esperaba, qué ha pasado y dónde mirar. Por dentro son los comandos del tema 4, que es lo que ejecuta CI sin ninguna skill: | ||
| + | |||
| + | ^ Verbo ^ Comando ^ | ||
| + | | ''/ | ||
| + | | ''/ | ||
| + | | ''/ | ||
| + | | ''/ | ||
| + | |||
| + | No hay un «todos» a propósito: los tipos se lanzan **uno a uno**, en ese orden, para saber en cada momento qué se está probando y contra qué. Para que '' | ||
| + | |||
| + | ===== Repararlos: /test < | ||
| + | |||
| + | Pasa mucho: se cambia algo del código, se refactoriza, | ||
| + | |||
| + | < | ||
| + | /test e2e repair | ||
| + | </ | ||
| + | |||
| + | El criterio es la **intención**: | ||
| + | |||
| + | * Un test está desactualizado solo si un cambio **intencionado** del código (un commit, o un cambio sin commitear que el alumno ha hecho a propósito) modificó o eliminó lo que el test comprueba: el texto de un mensaje, un campo, un flujo. Entonces se actualiza el test. | ||
| + | * Sin un cambio intencionado que lo justifique, el fallo es una **regresión**: | ||
| + | * Si no se sabe, **no se toca nada** y se pregunta. | ||
| + | |||
| + | Y tres reglas que no se negocian, porque sin ellas «reparar» acaba siendo «hacer que pase»: | ||
| + | |||
| + | * Nunca quita, comenta ni relaja una aserción, salvo que el cambio intencionado lo obligue. Nunca crea tests nuevos: para eso está '' | ||
| + | * Borra un test solo si lo que comprobaba ya no existe en la aplicación, | ||
| + | * Un test cada vez, sin commits, y al final una tabla: test, diagnóstico (desactualizado / regresión / sin determinar) y qué se ha cambiado. El alumno la lee y decide si está de acuerdo. | ||
| + | |||
| + | '' | ||
| + | |||
| + | ===== La revisión: /code review ===== | ||
| + | |||
| + | Sin pull request nadie mira el código antes de que llegue a '' | ||
| + | |||
| + | < | ||
| + | /code review | ||
| + | </ | ||
| + | |||
| + | Una sola revisión | ||
| + | |||
| + | ==== El código: contra la spec y las reglas ==== | ||
| + | |||
| + | Compara el diff de la rama contra '' | ||
| + | |||
| + | * **La spec del issue**: ¿hace lo que se pidió, y como se pidió? ¿Falta algún criterio de aceptación? | ||
| + | * **Las convenciones** ('' | ||
| + | * **Las reglas de calidad** de '' | ||
| + | |||
| + | Cada hallazgo lleva la **regla** incumplida, el **sitio** ('' | ||
| + | |||
| + | Un hallazgo bien hecho y dos mal hechos: | ||
| + | |||
| + | < | ||
| + | GRAVE PedidoService.java: | ||
| + | | ||
| + | | ||
| + | |||
| + | MAL " | ||
| + | (no mira las clases hermanas: todos los servicios lo escriben así; y no dice qué cuesta) | ||
| + | MAL "el método es demasiado largo" | ||
| + | (sin regla ni coste: es una opinión) | ||
| + | </ | ||
| + | |||
| + | Los graves se corrigen. Los mejorables los decide el alumno: o se dejan abiertos para que se corrijan con los graves, o se cierran a mano con un «no se hace, es así a propósito». Un hallazgo cerrado así no bloquea nada. | ||
| + | |||
| + | <note important> | ||
| + | |||
| + | ==== calidad-codigo: | ||
| + | |||
| + | '' | ||
| + | |||
| + | < | ||
| + | .claude/ | ||
| + | ├── SKILL.md | ||
| + | ├── metodos.md | ||
| + | ├── clases.md | ||
| + | ├── comentarios.md | ||
| + | └── tests.md | ||
| + | </ | ||
| + | |||
| + | **La máxima**: el código se escribe para que **una persona lo entienda al leerlo** y para que **un agente lo pueda modificar sin equivocarse**. Consecuencia que lo cambia todo: una repetición pequeña y visible es aceptable; una indirección para ahorrar dos líneas (un método que solo reenvía, un genérico) no lo es, porque el agente no olvida los dos sitios que hay que tocar y la persona sí pierde el hilo. | ||
| + | |||
| + | Cuando dos reglas chocan, gana la primera de esta lista: mantenibilidad, | ||
| + | |||
| + | ^ Fichero ^ Reglas (las que entran; se amplía con lo que salga en las revisiones) ^ | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | | '' | ||
| + | |||
| + | Y en '' | ||
| + | |||
| + | La '' | ||
| + | |||
| + | ==== Los tests: contra los criterios ==== | ||
| + | |||
| + | La misma revisión mira después los tests del issue: que **cada criterio de aceptación** de '' | ||
| + | |||
| + | ==== Las correcciones: | ||
| + | |||
| + | < | ||
| + | /code impl .kiro/ | ||
| + | </ | ||
| + | |||
| + | El mismo ''/ | ||
| - | * **'' | + | ===== Lo que comprueba /git-flow finish ===== |
| - | * **'' | + | |
| - | * **El smoke test** es el último paso: una petición a la URL de producción que tiene que responder 200. Si el despliegue ha dejado la aplicación caída, el workflow sale en rojo y se ve en el acto. | + | |
| - | * '' | + | |
| - | Y dos workflows pequeños de operación, '' | + | Con los tests y la revisión, '' |
| - | ===== La IA y los workflows ===== | + | - '' |
| + | - '' | ||
| + | - Los cuatro tipos de tests en verde: '' | ||
| - | El YAML lo escribe el agente a partir de lo de arriba. Y no hay skill para cuando CI sale en rojo, porque **no debería salir en rojo**: pasa los mismos comandos que '' | + | Si está todo, hace lo del tema 3: '' |
| ===== Ejercicios ===== | ===== Ejercicios ===== | ||
| ==== Ejercicio 1 ==== | ==== Ejercicio 1 ==== | ||
| - | * Crea un issue «CI» | + | * Crea un issue «Skill /test: create» |
| - | * Comprueba que '' | + | * Instala Playwright en '' |
| - | * Añade | + | * Escribe la skill ''/ |
| - | * Escribe | + | * ''/ |
| + | * ''/ | ||
| + | * Finaliza el issue. | ||
| ==== Ejercicio 2 ==== | ==== Ejercicio 2 ==== | ||
| - | | + | * Crea un issue «Skill /test: run y repair» |
| - | | + | * Añade el verbo '' |
| - | * Finaliza | + | * Introduce un error a mano en una validación del servicio, reconstruye |
| + | * Añade el verbo '' | ||
| + | * Cambia a propósito | ||
| + | * Finaliza el issue. | ||
| ==== Ejercicio 3 ==== | ==== Ejercicio 3 ==== | ||
| - | * Añade | + | * Crea un issue «Skill /code» e inícialo. |
| - | * Lánzalos desde //Actions// y lee la salida de '' | + | * Escribe la skill de conocimiento |
| + | * Añade a la skill '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * Finaliza | ||
| ==== Ejercicio 4 ==== | ==== Ejercicio 4 ==== | ||
| - | * Cambia a propósito la URL del smoke test por una que no existe, finaliza el issue y publica. CI pasa y '' | + | * Crea un issue «finish comprueba» e inícialo. |
| - | * Haz un cambio visible | + | * Amplía |
| + | * Deja una tarea sin marcar | ||
| - | Fuera de este tema, por ser de un sistema real y no de un proyecto | + | ==== Ejercicio 5 ==== |
| + | * Crea un issue para la segunda entidad | ||
| + | * ''/ | ||
| + | * '' | ||
| + | * ''/ | ||
| + | * ''/ | ||
clase/daw/daw-proyecto/tema06.txt · Última modificación: por claude
