La API de Escena Viva vende entradas, persiste pedidos con transacciones que impiden la sobreventa, autentica usuarios, rota tokens de refresco y autoriza operaciones según roles y propiedad del recurso. Hace muchísimas cosas. Y nadie ha comprobado nunca que funcione. Ni una sola vez.

npm test sigue fallando a propósito desde el módulo 5 con el mensaje Sin pruebas todavia — Modulo 9, y cada línea de seguridad que escribimos en el módulo anterior —el señuelo de bcrypt, la detección de reutilización del refresco, cada celda de la matriz de permisos— descansa hoy sobre la confianza de que la escribimos bien. Un if invertido en puedeGestionarEvento abriría el catálogo entero de eventos a cualquier organizador y nada avisaría.

En esta lección no escribiremos todavía la primera prueba ejecutable ni instalaremos nada: eso es la lección siguiente. Aquí construimos los cimientos conceptuales, que es lo que separa un proyecto con muchas pruebas de un proyecto con buenas pruebas.

Contenido

  1. Por qué se prueba: cambiar el código sin miedo
  2. Qué es una prueba automatizada y la estructura AAA
  3. Tipos de prueba y la pirámide
  4. Qué probar y qué no: el criterio del riesgo
  5. Qué hace buena a una prueba
  6. Pruebas frágiles y falsos positivos
  7. TDD explicado con honestidad
  8. El panorama de herramientas para Node
  9. El plan de pruebas de Escena Viva

Por qué se prueba: cambiar el código sin miedo

Existe una idea muy extendida de que las pruebas sirven "por si acaso", como un seguro que quizá algún día se cobre. Es una descripción pobre y explica por qué tantos equipos las abandonan a las tres semanas. El valor real de una batería de pruebas es otro y es medible en el día a día: te devuelve la capacidad de modificar el código.

Hagamos la prueba del algodón con nuestro propio proyecto. Responde con honestidad:

  • ¿Te atreverías hoy a reescribir comprarEntradas para agrupar varias sesiones en un solo pedido?
  • ¿Te atreverías a refactorizar PERMISOS_POR_ROL para añadir el rol taquillero sin revisar manualmente las 30 combinaciones?
  • ¿Te atreverías a cambiar el orden de dos middlewares en crearAplicacion para que autenticar corra antes que limiteCompra?
  • ¿Te atreverías a subir la versión mayor de Mongoose?

Si la respuesta honesta es "no, o solo con mucho cuidado y probando a mano en el navegador", el código ya te está gobernando a ti. Esa parálisis tiene un coste que no aparece en ninguna factura: las funciones se van copiando en lugar de reutilizarse, los if se acumulan porque nadie borra ramas antiguas, y la deuda técnica crece porque tocar lo que ya funciona da miedo.

Una batería de pruebas convierte la pregunta "¿habré roto algo?" en un comando de diez segundos. Ese es el producto que compramos en este módulo. Los beneficios secundarios son reales pero secundarios:

Beneficio Qué aporta de verdad
Detectar regresiones Un fallo que ya arreglaste no vuelve sin que te enteres
Documentación viva it('rechaza la venta si el aforo es insuficiente') no se desactualiza, porque si miente falla
Presión de diseño El código difícil de probar suele estar mal acoplado; probar lo revela pronto
Confianza en el despliegue CI puede bloquear un despliegue roto sin intervención humana
Onboarding Quien llega nuevo lee las pruebas para entender el comportamiento esperado

Y hay algo que las pruebas no hacen, conviene decirlo desde el principio: no demuestran que el programa sea correcto. Demuestran que los casos que se te ocurrieron se comportan como esperabas. Es muchísimo, pero no es una garantía matemática.

Qué es una prueba automatizada y la estructura AAA

Una prueba automatizada es simplemente un programa que ejecuta otro programa y comprueba el resultado, terminando con éxito o con error sin que nadie mire la pantalla. No hay magia: un fichero de pruebas es JavaScript normal.

La estructura universal se conoce como AAA (Arrange, Act, Assert), que en español llamaremos preparar, actuar y comprobar:

  1. Preparar: construir el escenario. Datos, objetos, dobles de prueba, estado inicial.
  2. Actuar: ejecutar exactamente una operación, la que se está probando.
  3. Comprobar: verificar que el resultado observable es el esperado.

Veamos el primer ejemplo sobre una pieza real de nuestro dominio, Sesion.vender(). Todavía no es código ejecutable con Mocha —falta la instalación—, pero la anatomía ya es la definitiva:

// Boceto conceptual de una prueba sobre Sesion.vender()
// (la sintaxis ejecutable con Mocha y Chai llega en 09-02)

const { Sesion } = require('../../src/dominio/sesion.js');

function pruebaVenderDescuentaDelAforo() {
  // 1. PREPARAR: una sesión conocida y controlada
  const sesion = new Sesion({
    id: 'ses-001-1',
    eventoId: 'evt-001',
    inicio: '2026-10-17T20:00:00.000Z',
    aforo: 400,
    vendidas: 100,
    precioCentimos: 2500,
  });

  // 2. ACTUAR: una sola operación
  sesion.vender(3);

  // 3. COMPROBAR: el efecto observable
  if (sesion.libres !== 297) {
    throw new Error('Se esperaban 297 localidades libres');
  }
}

Tres observaciones importantes sobre este boceto:

  • La preparación es explícita y local. No leemos la sesión de la base de datos ni dependemos de la semilla. Si mañana alguien cambia el aforo de ses-001-1 en scripts/semilla.js, esta prueba sigue siendo válida. Una prueba que depende de datos lejanos es una prueba que fallará por motivos ajenos a lo que dice probar.
  • Actuar es una sola línea. Si necesitas cinco llamadas para actuar, probablemente estés probando cinco cosas y el fallo no te dirá cuál.
  • Comprobamos el comportamiento observable, libres, no el campo privado #vendidas. De hecho no podríamos: es privado. Eso es una ventaja, no un obstáculo.

Un cuarto paso implícito, la limpieza, aparecerá cuando haya recursos que liberar (conexiones, relojes falsos, ficheros). En el dominio puro no hace falta, y ese es justo su encanto.

Tipos de prueba y la pirámide

No todas las pruebas cuestan lo mismo ni detectan lo mismo. Esta tabla es el mapa del módulo entero:

Tipo Qué ejercita Velocidad Coste de escritura Fragilidad Qué detecta
Unitaria Una función o clase aislada Milisegundos Bajo Baja Errores de lógica y de cálculo
Integración Varias piezas juntas (rutas + middleware + repositorio + BD) Décimas a segundos Medio Media Cableado, contratos entre capas, orden de middlewares
Extremo a extremo El sistema completo con navegador o cliente real Segundos a minutos Alto Alta Flujos de usuario completos, problemas de despliegue
De contrato El formato acordado entre dos servicios Rápida Medio Baja Cambios de API que romperían a un consumidor
De carga El sistema bajo presión Minutos Alto Alta Cuellos de botella, degradación, límites de recursos

Las tres primeras forman la pirámide de pruebas: muchas unitarias en la base, bastantes de integración en el medio, muy pocas de extremo a extremo en la punta.

graph TD
    E2E["Extremo a extremo<br/>pocas · lentas · frágiles<br/>flujos críticos de compra"]
    INT["Integración<br/>bastantes · medias<br/>rutas, middleware, repositorios, BD"]
    UNI["Unitarias<br/>muchas · rapidísimas · estables<br/>dominio, política, utilidades"]
    E2E --> INT
    INT --> UNI
    style E2E fill:#f8d7da,stroke:#842029
    style INT fill:#fff3cd,stroke:#664d03
    style UNI fill:#d1e7dd,stroke:#0f5132

La forma no es un capricho estético: es economía. Una prueba unitaria de puedeGestionarEvento tarda menos de un milisegundo y, cuando falla, te señala una función concreta. Una prueba de extremo a extremo del mismo permiso tarda diez segundos, puede fallar porque el navegador tardó en cargar, y cuando falla te dice "el botón no aparecía", que puede significar cincuenta cosas distintas.

El antipatrón del cono de helado

Cuando un equipo invierte la pirámide —muchísimas pruebas de extremo a extremo, algunas de integración, casi ninguna unitaria— obtiene el llamado cono de helado. Es un desastre reconocible por sus síntomas:

  • La batería tarda 40 minutos y la gente deja de ejecutarla en local.
  • Un cambio de una línea en una plantilla rompe treinta pruebas.
  • Aparecen pruebas intermitentes (flaky): fallan una de cada cinco veces sin motivo aparente.
  • Como fallan a menudo por ruido, el equipo empieza a reintentar hasta que pasen. En ese momento la batería ha dejado de aportar información y solo aporta espera.

La regla práctica: cada comportamiento se prueba al nivel más bajo que pueda demostrarlo. Sube de nivel solo cuando el nivel inferior no puede ver el problema.

Qué probar y qué no: el criterio del riesgo

Probarlo todo es imposible y perseguirlo produce baterías caras que envejecen mal. El criterio que usaremos es el riesgo, entendido como probabilidad de fallo multiplicada por el daño que causaría.

Sí se prueba:

  • Lógica de negocio con reglas. Sesion.vender() valida cantidad, aforo y estado. Si se equivoca, vendemos entradas que no existen.
  • La matriz de permisos. Un error aquí es una brecha de seguridad silenciosa.
  • Cálculos. Totales en céntimos, límites de 6 entradas por pedido, ocupación, umbral de aforo bajo.
  • El manejo de errores. Que RecursoNoEncontrado acabe siendo un 404 con el formato { error: { codigo, mensaje, estado, detalles } }.
  • Casos límite y frontera. Vender exactamente las últimas entradas, vender una más, cantidad cero, cantidad negativa.
  • Todo fallo que haya ocurrido en producción. Antes de arreglarlo, una prueba que lo reproduzca. Volveremos a esto en 09-06.

No se prueba (o se prueba muy poco):

  • Getters triviales. Si get precioEuros() { return this.precioCentimos / 100; } merece una prueba es discutible; si tuviera redondeo, sí, porque ahí hay una decisión.
  • Librerías de terceros. No es tu trabajo comprobar que Express enruta o que bcrypt hashea. Sí lo es comprobar cómo las usas.
  • Configuración estática. Que PERMISOS tenga cinco claves no dice nada; que un rol pueda o no usarlas, sí.
  • Detalles de implementación. Que un método llame internamente a otro método privado no es un comportamiento; es una decisión que quieres poder cambiar.
  • Código generado. Migraciones autogeneradas, ficheros de arranque triviales.

Qué hace buena a una prueba

Cuatro propiedades, en orden de importancia:

  1. Rápida. Si la batería unitaria tarda más de unos segundos, dejarás de ejecutarla mientras programas.
  2. Determinista. El mismo código con la misma entrada da siempre el mismo resultado. Nada de Date.now(), Math.random(), red o dependencia del orden. Todo eso lo domesticaremos con Sinon en 09-03.
  3. Aislada. No depende de que otra prueba se haya ejecutado antes ni deja residuos para la siguiente.
  4. Con un solo motivo de fallo. Cuando se pone roja, debe quedar claro qué comportamiento se rompió.

Y una quinta que no es técnica pero decide si la batería sobrevive: el nombre debe describir el comportamiento esperado, no el método invocado. El nombre es lo único que verás en la salida cuando falle a las tres de la mañana.

Nombre malo Por qué es malo Nombre bueno
prueba vender No dice qué se espera descuenta las localidades vendidas del aforo disponible
test 1 No dice nada en absoluto lanza ConflictoDeEstado si no quedan localidades suficientes
funciona No es falsable marca la sesion como agotada al vender la ultima entrada
politica Demasiado amplio permite al organizador de la sala editar su propio evento
no falla Ausencia de error no es comportamiento devuelve 422 si se piden mas de 6 entradas
caso 3 del ticket 481 El ticket desaparecerá impide que un asistente vea el pedido de otro asistente

Fíjate en que todos los nombres buenos empiezan por un verbo en tercera persona y describen el efecto observable. Leídos junto al describe que los contiene forman una frase: Sesion vender — lanza ConflictoDeEstado si no quedan localidades suficientes.

Pruebas frágiles y falsos positivos

Hay dos fallos de calidad que arruinan baterías enteras.

Prueba frágil es la que se rompe cuando el código cambia sin que el comportamiento cambie. Casi siempre nace de probar la implementación en lugar del comportamiento:

// FRÁGIL: comprueba cómo está hecho por dentro
// Si mañana el gestor calcula el total con reduce en vez de un bucle,
// esta prueba falla sin que nada se haya roto para el usuario.
prueba('gestor llama a calcularSubtotal una vez por linea', () => {
  const espia = espiarMetodoPrivado(gestor, 'calcularSubtotal');
  gestor.registrarVenta(pedido);
  comprobar(espia.llamadas === 2);
});

// ROBUSTO: comprueba qué se obtiene
prueba('el total del pedido suma el precio de todas sus lineas', () => {
  const pedido = gestor.registrarVenta({ lineas: [
    { cantidad: 2, precioCentimos: 2500 },
    { cantidad: 1, precioCentimos: 1800 },
  ] });
  comprobar(pedido.totalCentimos === 6800);
});

Falso positivo (o falso verde) es la prueba que pasa siempre, incluso con el código roto. Es peor que no tener prueba, porque genera confianza infundada. Las causas más habituales en Node:

  • Una promesa no esperada: el it termina antes de que la aserción se ejecute. Lo veremos en detalle en 09-02.
  • Una aserción dentro de un catch que nunca se ejecuta.
  • Simular tanto la dependencia que la prueba solo comprueba tus propias suposiciones (el peligro central de 09-03).

Truco profesional que usaremos varias veces en el módulo: cuando escribas una prueba, rómpela a propósito. Cambia un signo en el código de producción y comprueba que se pone roja. Una prueba que nunca has visto fallar no es una prueba, es una esperanza.

TDD explicado con honestidad

El desarrollo dirigido por pruebas (Test-Driven Development) invierte el orden habitual: primero la prueba, después el código.

graph LR
    R["ROJO<br/>escribe una prueba<br/>que falla"] --> V["VERDE<br/>el código mínimo<br/>que la hace pasar"]
    V --> RF["REFACTOR<br/>mejora el diseño<br/>sin tocar la prueba"]
    RF --> R
    style R fill:#f8d7da,stroke:#842029
    style V fill:#d1e7dd,stroke:#0f5132
    style RF fill:#cfe2ff,stroke:#084298

Un ciclo completo sobre una regla real de Escena Viva: ningún pedido puede superar las 6 entradas por sesión.

Rojo. Escribimos la prueba antes de que exista la comprobación:

// La regla todavía no está implementada: esta prueba DEBE fallar.
prueba('rechaza un pedido de mas de 6 entradas para la misma sesion', () => {
  const sesion = crearSesion({ aforo: 400, vendidas: 0 });
  let lanzo = false;
  try {
    sesion.vender(7);
  } catch (error) {
    lanzo = true;
  }
  comprobar(lanzo === true);
});

Ejecutamos y falla. Este paso no es burocracia: verifica que la prueba sabe detectar el fallo. Si pasara ya en rojo, la prueba estaría mal escrita.

Verde. El código mínimo que la satisface:

// src/dominio/sesion.js (fragmento)
const MAXIMO_POR_PEDIDO = 6;

vender(cantidad) {
  if (!Number.isInteger(cantidad) || cantidad < 1) {
    throw new ErrorDeValidacion('La cantidad debe ser un entero positivo');
  }
  if (cantidad > MAXIMO_POR_PEDIDO) {
    throw new ErrorDeValidacion(`Maximo ${MAXIMO_POR_PEDIDO} entradas por pedido`);
  }
  // ...resto de la lógica de aforo
}

Refactor. Ahora sí mejoramos: extraemos MAXIMO_POR_PEDIDO a una constante exportada para que el esquema zod y el mensaje de error usen el mismo número, y añadimos el detalles del error con el máximo permitido. La prueba nos protege durante el cambio.

Y ahora la honestidad prometida:

TDD ayuda mucho cuando... TDD estorba cuando...
La regla de negocio está clara y es verificable Estás explorando una API que no conoces
Arreglas un fallo (la prueba lo reproduce primero) Maquetas una interfaz visual
Diseñas una función pura, como la política de permisos El diseño va a cambiar tres veces esta tarde
Trabajas sobre código legado y quieres fijar el comportamiento actual Escribes un script de un solo uso

No es una religión. En este curso escribiremos algunas pruebas antes y muchas después, y en 09-06 usaremos TDD de forma estricta para una cosa concreta en la que es indiscutible: reproducir un fallo antes de arreglarlo.

El panorama de herramientas para Node

Herramienta Qué es Puntos fuertes Inconvenientes
Mocha Ejecutor de pruebas Maduro, flexible, no impone aserciones ni dobles, configuración transparente Hay que montar la pila (Chai, Sinon) tú mismo
Chai Librería de aserciones expect muy legible, mensajes de fallo claros, extensible Dependencia extra
Sinon Dobles de prueba Espías, stubs, relojes falsos, el estándar de facto Fácil de abusar
supertest Cliente HTTP para pruebas Prueba una app de Express sin listen manual Solo HTTP
c8 / nyc Cobertura c8 usa la cobertura nativa de V8, sin instrumentar Métrica fácil de malinterpretar
Jest Todo en uno Ejecutor, aserciones, mocks y cobertura juntos; instantáneas Opinado; su transformación complica el CommonJS/ESM puro
Vitest Todo en uno moderno Rapidísimo, API compatible con Jest, gran soporte ESM Nació en el mundo Vite; menos común en APIs puras de Node
node:test Ejecutor nativo Cero dependencias, incluido en Node, con --test y cobertura integrada API más joven, ecosistema de complementos menor

El ejecutor nativo merece un párrafo honesto. Desde Node 20 es estable y perfectamente utilizable:

// Cómo se vería con el ejecutor nativo (referencia, no lo usaremos)
const { test } = require('node:test');
const assert = require('node:assert/strict');

test('descuenta las localidades vendidas del aforo', () => {
  const sesion = crearSesion({ aforo: 400, vendidas: 100 });
  sesion.vender(3);
  assert.equal(sesion.libres, 297);
});

Si empezaras un proyecto nuevo hoy, node:test es una elección defendible y sin dependencias.

Por qué este curso usa Mocha + Chai + Sinon + supertest: porque es la pila más extendida en las APIs de Node que te vas a encontrar en producción, porque separa con claridad las tres responsabilidades (ejecutar, afirmar, simular) y eso enseña mejor los conceptos, porque su documentación de errores es explícita, y porque las ideas se trasladan a cualquier otra pila en una tarde. Elegida la pila, no cambiaremos a mitad del módulo: mezclar ejecutores es una fuente clásica de confusión.

El plan de pruebas de Escena Viva

Este es el recorrido del módulo:

Lección Qué se prueba Herramientas
09-02 Dominio puro: Sesion, Evento, GestorDeVentas, y la matriz completa de politica.js Mocha, Chai
09-03 Unidades con dependencias: cambio-divisas.js, tokens que caducan, repositorios Sinon
09-04 La API real de punta a punta: compra, rechazos 401/403/404/409/422, concurrencia supertest
09-05 Cobertura, umbrales, scripts de npm, pruebas intermitentes, preparación para CI c8
09-06 Depuración de lo que falle: inspector, VS Code, trazas, fugas de memoria Node y DevTools

La estructura de carpetas que crearemos, espejo de src/:

escena-viva/
├── src/
│   ├── dominio/
│   ├── autorizacion/
│   ├── repositorios/
│   └── ...
├── test/
│   ├── unidad/
│   │   ├── sesion.test.js
│   │   ├── evento.test.js
│   │   ├── politica.test.js
│   │   └── gestor-ventas.test.js
│   ├── integracion/
│   │   ├── eventos.test.js
│   │   └── pedidos.test.js
│   └── ayudas/
│       ├── fabricas.js
│       └── autenticacion.js
└── .mocharc.json

Tres convenciones que seguiremos sin excepción:

  • Sufijo .test.js en todos los ficheros de prueba: hace trivial el patrón de búsqueda de Mocha y distingue las pruebas de las ayudas.
  • Espejo del código fuente: src/dominio/sesion.js se prueba en test/unidad/sesion.test.js. Encontrar la prueba de un fichero nunca debe requerir una búsqueda.
  • test/ayudas/ no contiene pruebas, solo utilidades compartidas: fábricas de datos y la ayuda de autenticación que resolverá la promesa del módulo 8.

Errores Comunes y Consejos

  • Escribir pruebas para subir un número. La cobertura es un indicador, no un objetivo. Lo trataremos a fondo en 09-05, pero interiorízalo ya: una prueba que ejecuta código sin comprobar nada sube la cobertura y no protege de nada.
  • Empezar por las pruebas de extremo a extremo porque "prueban de verdad". Acabarás con el cono de helado y una batería que nadie ejecuta.
  • Probar métodos privados. Si sientes esa necesidad, normalmente esa lógica quiere ser una función pública en otro módulo. #vendidas se prueba a través de libres y agotada.
  • Pruebas que dependen del orden. "Funciona si ejecutas todo el fichero pero falla sola" es el síntoma. Cada it debe poder ejecutarse en solitario.
  • Reutilizar objetos entre pruebas para "no repetir". Compartir un objeto mutable entre it es la causa número uno de pruebas intermitentes. Usa fábricas que devuelvan objetos nuevos.
  • Consejo: empieza por la capa de mayor riesgo y menor coste. En Escena Viva eso es src/autorizacion/politica.js: funciones puras, sin dependencias, protegiendo lo más sensible del sistema. Se prueba entera en cincuenta líneas.
  • Consejo: trata el código de las pruebas como código de producción. Se lee más veces de las que se escribe y hay que mantenerlo.

Ejercicios

Ejercicio 1: clasificar por nivel

Para cada comportamiento de Escena Viva, indica a qué nivel de la pirámide lo probarías y por qué:

  1. El total de un pedido de 2 entradas a 2500 céntimos es 5000.
  2. POST /api/pedidos sin cabecera Authorization devuelve 401.
  3. Un organizador de org-boveda no puede editar evt-001, que pertenece a org-almendra.
  4. El middleware limiteCompra se aplica antes que el controlador de pedidos.
  5. hashearContrasena usa coste 12.

Ejercicio 2: reescribir nombres

Reescribe estos nombres de prueba siguiendo las reglas de la lección:

  1. test comprarEntradas
  2. politica funciona bien
  3. error 409
  4. no peta con cantidad 0

Ejercicio 3: diseñar un ciclo TDD

Escribe (en pseudocódigo, sin ejecutar) el ciclo rojo-verde-refactor para esta regla nueva: una sesión que ya ha comenzado no admite ventas. Indica qué prueba escribirías primero, qué código mínimo la haría pasar y qué refactorizarías después.

Soluciones

Ejercicio 1

  1. Unitaria. Es un cálculo puro en el dominio; no necesita HTTP ni base de datos.
  2. Integración. El 401 nace de la combinación ruta + middleware autenticar + manejadorDeErrores. Ninguna prueba unitaria del middleware garantiza que esté realmente montado en esa ruta.
  3. Unitaria, con puedeGestionarEvento, porque es una función pura y podemos recorrer la matriz entera barata y exhaustivamente. Además una prueba de integración de confirmación (403 real por HTTP), no las treinta.
  4. Integración. El orden de los middlewares solo es observable ejecutando la aplicación real: es exactamente lo que las pruebas unitarias no pueden ver.
  5. Ninguna, o casi. Es una constante de configuración. Probar el coste exacto de bcrypt es probar la librería; sí tiene sentido una prueba de que verificarContrasena acepta el hash que produce hashearContrasena (comportamiento, no detalle).

Ejercicio 2

  1. crea un pedido con estado pendiente y descuenta el aforo de la sesion
  2. permite al administrador gestionar cualquier evento
  3. devuelve ConflictoDeEstado si las localidades libres son menores que las solicitadas
  4. lanza ErrorDeValidacion si la cantidad es cero

Ejercicio 3

Rojo: prueba rechaza la venta si la sesion ya ha comenzado, que crea una sesión con inicio en el pasado, llama a vender(1) y espera un ConflictoDeEstado. Falla porque vender no mira la fecha.

Verde: añadir al principio de vender una comprobación if (new Date(this.inicio) <= new Date()) { throw new ConflictoDeEstado('La sesion ya ha comenzado'); }.

Refactor: extraer un getter get haComenzado() que encapsule la comparación, reutilizable por el catálogo para no listar sesiones pasadas, e inyectar el reloj en lugar de llamar a new Date() directamente. Ese último punto es justo lo que hace posible la lección 09-03: el código que depende del reloj real no se puede probar de forma determinista.

Conclusión

Hemos puesto los cimientos. Sabemos por qué se prueba —para poder cambiar el código sin miedo, no por si acaso—, cómo se estructura una prueba con preparar, actuar y comprobar, qué niveles existen y por qué la pirámide tiene la forma que tiene, qué merece prueba según el riesgo y qué no, qué propiedades hacen buena a una prueba, cómo distinguir una prueba frágil de una robusta, cuándo TDD ayuda de verdad y qué herramientas hay en el ecosistema de Node.

También tenemos el plan: test/unidad/, test/integracion/, test/ayudas/, ficheros *.test.js, y la pila Mocha + Chai + Sinon + supertest.

Lo que no tenemos todavía es una sola línea ejecutable. En la lección siguiente, Pruebas Unitarias con Mocha y Chai, instalamos la pila, arreglamos de una vez el script test que lleva cuatro módulos fallando a propósito, y escribimos la batería unitaria completa del dominio de Escena Viva, incluida esa tabla de casos que recorre la matriz de permisos celda por celda que llevamos prometiendo desde el módulo 8.

Curso de Node.js: De Principiante a Avanzado

Módulo 1: Introducción a Node.js

Módulo 2: Conceptos Básicos

Módulo 3: Sistema de Archivos y E/S

Módulo 4: HTTP y Servidores Web

Módulo 5: NPM y Gestión de Paquetes

Módulo 6: Framework Express.js

Módulo 7: Bases de Datos y ORMs

Módulo 8: Autenticación y Autorización

Módulo 9: Pruebas y Depuración

Módulo 10: Temas Avanzados

Módulo 11: Despliegue y DevOps

Módulo 12: Proyectos del Mundo Real

© Copyright 2026. Todos los derechos reservados