Skip to content

Tests iniciales - José de la Fuente - #3

Open
josedelafuente wants to merge 1 commit into
LIDR-academy:mainfrom
josedelafuente:tests-iniciales
Open

Tests iniciales - José de la Fuente#3
josedelafuente wants to merge 1 commit into
LIDR-academy:mainfrom
josedelafuente:tests-iniciales

Conversation

@josedelafuente

Copy link
Copy Markdown

Suite de tests para la inserción de candidatos, cubriendo las dos familias del enunciado: recepción de los datos del formulario y guardado en la base de datos.

28 tests en verde. Ninguna línea de código de producción modificada.

Qué incluye

Archivo Contenido
backend/src/tests/tests-iniciales.test.ts La suite completa
prompts/prompts-iniciales.md Los prompts, el método y las decisiones de alcance
backend/jest.config.js Ver la nota al final

Familia 1 — recepción de datos. Validación unitaria pura sobre validateCandidateData: las validaciones de campo agrupadas en un test.each de 12 filas, más formación, experiencia laboral y CV.

Familia 2 — guardado en base. addCandidate y Candidate.save con el cliente de Prisma mockeado. El mock va en la frontera arquitectónica —el paquete @prisma/client— y no más adentro: prisma se instancia a nivel de módulo en cada modelo, sin inyección de dependencias, así que no hay otro punto de sustitución posible.

El problema de método, y cómo se resolvió

El código de inserción ya existía antes de escribir el primer test, así que el ciclo rojo previo no estaba disponible. Escribir tests sobre código que ya funciona produce validación circular: los tests pasan por construcción y nadie sabe si detectan algo.

La verificación que reemplaza al rojo previo fue mutación manual: un script rompe a propósito la línea de producción que sostiene cada aserción, corre la suite, registra qué test cae y restaura el archivo. Si el patrón a mutar no aparece, aborta en vez de seguir — una mutación que no llegó a aplicarse y da verde se leería como que el test no detecta el defecto, que es la conclusión contraria.

Resultado: 17 de 17 mutaciones detectadas.

Lo que encontró

En la primera pasada una mutación sobrevivió. Quitando el guard if (this.phone !== undefined) de Candidate.save(), los campos opcionales ausentes empiezan a viajar a Prisma como undefined — y el test que decía verificar exactamente eso siguió en verde.

El motivo es que toHaveBeenCalledWith y toEqual ignoran las claves cuyo valor es undefined: para ellos { email, phone: undefined } es igual a { email }. El test estaba escrito, pasaba, y no verificaba lo que su nombre afirmaba. Test Theater dentro del propio entregable, encontrado solo porque se lo sometió a mutación. Corregido con toStrictEqual, el único matcher que distingue la clave ausente de la clave en undefined.

Dos comportamientos fijados como caracterización

Van marcados en el archivo con el prefijo COMPORTAMIENTO ACTUAL. Fijan lo que el código hace hoy para que un cambio futuro sea visible; no afirman que esté bien.

1. Un id en el payload omite toda la validación. validateCandidateData devuelve en su primera línea si el payload trae id (application/validator.ts:81), con el comentario "si viene el id, estamos editando". Combinado con Candidate.save(), que con id hace prisma.candidate.update (domain/models/Candidate.ts:76), el endpoint de alta acepta un payload con un id ajeno y modifica ese candidato sin validar ninguno de sus campos. El enunciado declara que la API recibirá datos desde fuentes externas, entre ellas la aplicación directa del candidato y sistemas de parsing automatizado.

2. La formación nunca se inserta anidada. El constructor de Candidate lee data.education en singular (Candidate.ts:26) mientras el servicio pasa educations en plural (candidateService.ts:20). Por esta vía this.education queda siempre vacío y el bloque que arma el nested create de Prisma no llega a ejecutarse: la formación se guarda después, en su propio insert. El test lo fija para que, el día que alguien corrija el nombre del campo, el doble insert resultante salga en rojo en vez de pasar inadvertido.

Un tercer hallazgo quedó como test normal: addCandidate reenvía el fallo de validación con throw new Error(error) (candidateService.ts:11), lo que estringifica el Error original y hace que el mensaje que llega al cliente sea "Error: Invalid email" y no "Invalid email". La aserción va anclada con una expresión regular, porque toThrow('Invalid email') hace match parcial y dejaría pasar el defecto.

Cómo probarlo

cd backend
npm install
npx jest --verbose

Para ver que los tests detectan algo, romper el regex del teléfono en src/application/validator.ts:3 y volver a correr: cae phone = "512345678" -> Invalid phone.

Una nota sobre el alcance

El enunciado pide que el PR solo incluya los dos archivos de la entrega. Va un tercero, backend/jest.config.js: el repositorio base trae jest y ts-jest declarados y el script test, pero no la configuración, así que sin ese archivo la suite no se puede ejecutar. Un PR de tests que no corren pareció peor que un archivo de más. Si corresponde sacarlo, se quita sin problema.


Trabajado con Claude Code sobre el repositorio. El detalle de los prompts, las decisiones de alcance y el reparto de autoría está en prompts/prompts-iniciales.md.

Dos familias, según el enunciado: recepción de los datos del formulario
(validación unitaria pura) y guardado en base (Prisma mockeado en la
frontera arquitectónica).

Como el código de producción ya existía, el ciclo rojo previo no estaba
disponible. Cada aserción se validó por mutación manual: romper la línea
que la sostiene y comprobar que el test cae. 17 de 17 mutaciones
detectadas. La primera pasada encontró un test propio que pasaba sin
verificar nada (toHaveBeenCalledWith ignora las claves en undefined),
corregido con toStrictEqual.

Ninguna línea de código de producción fue modificada.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fc0376f-00a4-4352-a3e0-ca008b6f7d97


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@LIDR-AI4Devs LIDR-AI4Devs left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔬 REVISIÓN DETALLADA: Tests Iniciales — TDD

📊 SCORING GLOBAL

Categoría Score Max Notas
Calidad de Prompts 28 30 Prompts con metodología: derivar→recortar→invertir→mutar→revisar
Calidad de Tests (Arch + Clean + Seg + Cov) 36 40 28 tests, mocking en frontera arquitectónica, hallazgos de bugs reales
Coherencia Prompt-Tests 19 20 Proceso auditable: cada caso tiene referencia archivo:línea
Documentación 10 10 PR body excepcional + prompts con tabla de autoría
Base 93 100

Bonus aplicados:

  • +5 🌟 Mutación manual como verificación — 17/17 mutaciones detectadas, reemplaza el rojo previo imposible
  • +5 🌟 Hallazgo de Test Theater — Descubrió que toEqual ignora claves con undefined, corrigió con toStrictEqual
  • +5 🌟 Documentación de bugs de producción — id omite validación, education/educations singular/plural, Error wrapping

SCORE FINAL: 108/100 — ⭐⭐⭐⭐⭐ (Excepcional)


🔍 ANÁLISIS DETALLADO

Calidad de Prompts — 28/30

Archivo: prompts/prompts-iniciales.md (8KB, ~160 líneas)

El documento no es un prompt único sino un sistema de 5 prompts secuenciales con metodología explícita. Cada uno construye sobre el anterior y ataca un problema concreto del ejercicio.

Secuencia de prompts:

  1. Derivar los casos del comportamiento — Pide lista de comportamientos con referencia archivo:línea para hacer auditable cada caso
  2. Recortar antes de escribir — Reduce scope antes de generar código, evitando el patrón "pedir suite completa y quedarse con lo que salga"
  3. Prompt de inversión — "Dime qué línea tendría que cambiar para que falle" — ancla cada aserción en una línea concreta
  4. Mutación manual — Script que rompe producción, corre tests, registra rojos y restaura — 17/17 detectadas
  5. Revisión final — Cruza resultado contra enunciado, descarta lo que sobra

Técnicas identificadas:

  • Meta-prompting: El prompt #3 (inversión) es meta-prompting puro — obliga al modelo a razonar sobre la calidad de sus propios tests
  • Constraint-Based: Recorte explícito de alcance, exclusión deliberada de casos de bajo valor
  • Verificación empírica: La mutación manual NO es un prompt sino una verificación independiente — el alumno no confía en el modelo para validar sus propios tests

Aspectos destacados:

  • La tabla de autoría (Pieza / Producida por / Decidida y aprobada por) es un modelo de transparencia sobre el reparto humano-IA
  • El análisis del "problema de partida" (código ya existente → validación circular) muestra comprensión profunda de la limitación del ejercicio
  • La distinción entre "test de caracterización" (fija comportamiento actual) y "test que verifica requisito" es conscientemente manejada

Debilidades:

  • ⚠️ El prompt principal no se incluye textualmente (se describe el enfoque pero no el prompt exacto que generó la suite). Para reproducibilidad, incluir el prompt literal habría sido ideal.

Calidad de Tests — 36/40

28 tests en verde, 0 líneas de producción modificadas.

Arquitectura — 9/10

  • ✅ Mock en la frontera arquitectónica (@prisma/client) — decisión argumentada por la ausencia de inyección de dependencias
  • test.each de 12 filas para validaciones de campo — compacto sin perder cobertura
  • ✅ Tests de caracterización marcados con prefijo COMPORTAMIENTO ACTUAL — distinguibles de los tests de requisito

Cobertura — 9/10

  • ✅ Familia 1: validación de campos con test.each, formación, experiencia, CV
  • ✅ Familia 2: create, update, email duplicado (P2002), propagación de id
  • ✅ Hallazgos de bugs: id omite validación, education/educations, Error wrapping
  • ⚠️ Alcance deliberadamente recortado (28 tests vs 80+ posibles) — decisión consciente pero reduce cobertura

Clean Code — 9/10

  • ✅ Naming descriptivo, en español
  • toStrictEqual donde importa (hallazgo documentado)
  • ✅ Regex en toThrow para anclar el mensaje exacto sin match parcial
  • ✅ Separación clara de caracterización vs requisito

Innovación — 9/10

  • ✅ Mutación manual con script automatizado — técnica senior
  • ✅ Detección de Test Theater (toEqual ignora undefined) — hallazgo valioso
  • ✅ Decisión de excluir PrismaClientInitializationError y P2025 por "bajo valor y mucho andamiaje" — criterio profesional

Coherencia Prompt-Tests — 19/20

La coherencia es excepcional porque el proceso es trazable:

  • Cada caso tiene su referencia archivo:línea
  • Cada recorte tiene justificación explícita
  • Cada aserción fue sometida a inversión antes de escribirse
  • El resultado fue verificado con mutación independiente

El único punto que impide 20/20 es que los prompts exactos no están incluidos textualmente — se describe la metodología pero no se puede reproducir el prompt #1 literal.


Documentación — 10/10

  • ✅ PR body es un mini paper: problema, método, hallazgos, resultados, alcance
  • ✅ Prompts documentan el proceso completo con razonamiento
  • ✅ Tabla de autoría humano/IA — modelo de transparencia
  • ✅ Instrucciones de ejecución (cd backend; npm install; npx jest --verbose)
  • ✅ Justificación del archivo extra (jest.config.js)
  • ✅ Nota sobre el "test que muestra que los tests detectan algo" (romper regex del teléfono)

📈 OBSERVACIONES PARA EL EQUIPO DOCENTE

  1. El enfoque metodológico es referente. La secuencia derivar→recortar→invertir→mutar→revisar resuelve el problema pedagógico central del ejercicio (escribir tests sobre código existente).

  2. El hallazgo de Test Theater (toEqual vs toStrictEqual con undefined) es un aprendizaje transferible a toda la cohorte — considerar mencionarlo en la sesión.

  3. La tabla de autoría establece un estándar para futuras entregas: qué hizo el modelo, qué decidió el humano.

  4. Comparación con PR #2 (@matc4): Ambos son excepcionales pero con enfoques opuestos — matc4 define CAs formales en el prompt y deja que fallen tests; josedelafuente parte del código existente y verifica con mutación. Ambos atacan el mismo problema (validación circular) desde ángulos complementarios.


Revisión generada por Agente Revisor Lidr | PR #3 | @josedelafuente | 2026-08-19

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants