Pruebas en JavaScript: desde pruebas unitarias hasta pruebas de extremo a extremo
\n\nLas pruebas de calidad son una parte esencial del desarrollo profesional en JavaScript. En este artículo, analizaremos tres niveles principales de pruebas: unitarias (unit), de integración (integration) y de extremo a extremo (e2e). Aprenderá qué herramientas utilizar, cómo escribir pruebas en Node.js y cómo construir una estrategia de pruebas eficaz.
\n\n1. Pruebas unitarias: la base de la pirámide de pruebas
\n\nLas pruebas unitarias verifican módulos aislados: funciones, clases o métodos individuales. La regla principal: el código bajo prueba no debe depender de recursos externos (bases de datos, API, sistema de archivos).
\n\nHerramientas para pruebas unitarias
\n- \n
- Jest — el framework más popular de Facebook. Incluye mocks, snapshots y cobertura de código de forma nativa. \n
- Mocha + Chai — un dúo flexible para quienes prefieren configurar todo manualmente. \n
- Vitest — un análogo moderno de Jest, optimizado para proyectos con Vite. \n
// Ejemplo de prueba unitaria con Jest\nconst { calculateDiscount } = require('./pricing');\n\ndescribe('calculateDiscount', () => {\n test('devuelve un 10% de descuento para montos > 1000', () => {\n const result = calculateDiscount(1500);\n expect(result).toBe(1350);\n });\n\n test('no aplica descuento para montos <= 1000', () => {\n const result = calculateDiscount(500);\n expect(result).toBe(500);\n });\n\n test('maneja el valor límite de 1000', () => {\n const result = calculateDiscount(1000);\n expect(result).toBe(1000);\n });\n});\n\nMejores prácticas para pruebas unitarias
\n- \n
- Pruebe un comportamiento a la vez (un assert por prueba). \n
- Utilice nombres descriptivos para las pruebas (given/when/then). \n
- Evite probar métodos privados — pruebe la interfaz pública. \n
- Mantenga la cobertura de código en un nivel del 70-80%. \n
2. Pruebas de integración: verificación de la interacción entre componentes
\n\nLas pruebas de integración verifican cómo funcionan juntos diferentes módulos. En el contexto de Node.js, esto generalmente implica probar con una base de datos real, sistema de archivos o API externas.
\n\nEscenarios típicos de pruebas de integración
\n- \n
- Interacción del controlador con la capa de servicios y la base de datos. \n
- Verificación de middleware y rutas de Express/Koa. \n
- Pruebas de repositorios con una base de datos de prueba (SQLite en memoria o PostgreSQL en Docker). \n
// Ejemplo de prueba de integración con Supertest y Jest\nconst request = require('supertest');\nconst app = require('../app');\nconst { createTestUser, cleanDatabase } = require('./helpers');\n\nbeforeEach(async () => {\n await cleanDatabase();\n});\n\ndescribe('POST /api/users', () => {\n test('crea un usuario y devuelve 201', async () => {\n const response = await request(app)\n .post('/api/users')\n .send({ name: 'Iván', email: 'ivan@test.com' });\n\n expect(response.status).toBe(201);\n expect(response.body).toHaveProperty('id');\n expect(response.body.name).toBe('Iván');\n });\n\n test('devuelve 400 al duplicar el email', async () => {\n await createTestUser({ email: 'ivan@test.com' });\n\n const response = await request(app)\n .post('/api/users')\n .send({ name: 'Pedro', email: 'ivan@test.com' });\n\n expect(response.status).toBe(400);\n expect(response.body.error).toBe('El email ya está en uso');\n });\n});\n\nConfiguración de la infraestructura de pruebas
\n- \n
- Docker Compose — para levantar servicios de prueba (BD, Redis). \n
- Testcontainers — gestión programática de contenedores desde las pruebas. \n
- Bases de datos en memoria (por ejemplo, mongodb-memory-server) — para pruebas rápidas sin dependencias externas. \n