# Ejecutar pruebas de Node.js en un contenedor


## Requisitos previos

Completa todas las secciones anteriores de esta guía, comenzando con [Contenedorizar una aplicación de Node.js](/guides/nodejs/run-tests/containerize/).

## Descripción general

Las pruebas son una parte fundamental para crear software confiable. Ya sea que escribas pruebas unitarias, de integración o de extremo a extremo (end-to-end), ejecutarlas de manera consistente en diferentes entornos es muy importante. Docker facilita esto al brindarte la misma configuración localmente, en CI/CD y durante la construcción de la imagen.

## Ejecutar pruebas al desarrollar localmente

La aplicación de ejemplo utiliza Vitest para las pruebas y ya incluye pruebas para componentes de React, hooks personalizados, rutas de API, operaciones de base de datos y funciones de utilidad.

### Ejecutar pruebas localmente (sin Docker)

```console
$ npm run test
```

### Agregar el servicio de pruebas a Docker Compose

Para ejecutar pruebas en un entorno contenedorizado, necesitas agregar un servicio de pruebas dedicado a tu archivo `compose.yml`. Agrega la siguiente configuración de servicio:

```yaml
services:
  # ... servicios existentes ...

  # ========================================
  # Servicio de pruebas
  # ========================================
  app-test:
    build:
      context: .
      dockerfile: Dockerfile
      target: test
    container_name: todoapp-test
    environment:
      NODE_ENV: test
      POSTGRES_HOST: db
      POSTGRES_PORT: 5432
      POSTGRES_DB: todoapp_test
      POSTGRES_USER: todoapp
      POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-todoapp_password}'
    depends_on:
      db:
        condition: service_healthy
    command: ['npm', 'run', 'test:coverage']
    networks:
      - todoapp-network
    profiles:
      - test
```

Esta configuración del servicio de pruebas:

- **Se construye desde la etapa de pruebas**: Utiliza el objetivo (target) `test` de tu Dockerfile multietapa.
- **Base de datos de pruebas aislada**: Utiliza una base de datos `todoapp_test` independiente para las pruebas.
- **Basado en perfiles**: Utiliza el perfil `test` para que solo se ejecute cuando se solicite explícitamente.
- **Dependencia de estado de salud**: Espera a que la base de datos esté saludable (healthy) antes de iniciar las pruebas.

### Ejecutar pruebas en un contenedor

Puedes ejecutar las pruebas utilizando el servicio de pruebas dedicado:

```console
$ docker compose up app-test --build
```

O ejecutar las pruebas en el servicio de desarrollo:

```console
$ docker compose run --rm app-dev npm run test
```

Para una ejecución única de pruebas con cobertura:

```console
$ docker compose run --rm app-dev npm run test:coverage
```

### Ejecutar pruebas con cobertura

Para generar un informe de cobertura:

```console
$ npm run test:coverage
```

Deberías ver una salida como la siguiente:

```console
> docker-nodejs-sample@1.0.0 test
> vitest --run

 ✓ src/server/__tests__/routes/todos.test.ts (5 tests) 16ms
 ✓ src/shared/utils/__tests__/validation.test.ts (15 tests) 6ms
 ✓ src/client/components/__tests__/LoadingSpinner.test.tsx (8 tests) 67ms
 ✓ src/server/database/__tests__/postgres.test.ts (13 tests) 136ms
 ✓ src/client/components/__tests__/ErrorMessage.test.tsx (8 tests) 127ms
 ✓ src/client/components/__tests__/TodoList.test.tsx (8 tests) 147ms
 ✓ src/client/components/__tests__/TodoItem.test.tsx (8 tests) 218ms
 ✓ src/client/__tests__/App.test.tsx (13 tests) 259ms
 ✓ src/client/components/__tests__/AddTodoForm.test.tsx (12 tests) 323ms
 ✓ src/client/hooks/__tests__/useTodos.test.ts (11 tests) 569ms

 Test Files  9 passed (9)
      Tests  88 passed (88)
    Start at  20:57:19
    Duration  4.41s (transform 1.79s, setup 2.66s, collect 5.38s, tests 4.61s, environment 14.07s, prepare 4.34s)
```

### Estructura de las pruebas

La suite de pruebas cubre:

- **Componentes del cliente** (`src/client/components/__tests__/`): Pruebas de componentes de React con React Testing Library.
- **Hooks personalizados** (`src/client/hooks/__tests__/`): Pruebas de hooks de React con simulaciones (mocking) adecuadas.
- **Rutas del servidor** (`src/server/__tests__/routes/`): Pruebas de puntos de enlace (endpoints) de la API.
- **Capa de base de datos** (`src/server/database/__tests__/`): Pruebas de operaciones de base de datos PostgreSQL.
- **Funciones de utilidad** (`src/shared/utils/__tests__/`): Pruebas de validación y funciones auxiliares.
- **Pruebas de integración** (`src/client/__tests__/`): Pruebas de integración de toda la aplicación.

## Ejecutar pruebas al construir

Para ejecutar pruebas durante el proceso de construcción de Docker, necesitas agregar una etapa de pruebas dedicada a tu Dockerfile. Si aún no has agregado esta etapa, añade lo siguiente a tu Dockerfile multietapa:

```dockerfile
# ========================================
# Etapa de pruebas
# ========================================
FROM build-deps AS test

# Configurar el entorno
ENV NODE_ENV=test \
    CI=true

# Copiar archivos fuente
COPY --chown=nodejs:nodejs . .

# Cambiar a usuario no root
USER nodejs

# Ejecutar pruebas con cobertura
CMD ["npm", "run", "test:coverage"]
```

Esta etapa de pruebas:

- **Entorno de pruebas**: Configura `NODE_ENV=test` y `CI=true` para una correcta ejecución de las pruebas.
- **Usuario no root**: Ejecuta las pruebas como el usuario `nodejs` por seguridad.
- **Ejecución flexible**: Utiliza `CMD` en lugar de `RUN` para permitir la ejecución de pruebas durante la construcción o como un contenedor independiente.
- **Soporte de cobertura**: Configurado para ejecutar pruebas con informes de cobertura.

### Construir y ejecutar pruebas durante la construcción de la imagen

Para construir una imagen que ejecute las pruebas durante el proceso de construcción, puedes crear un Dockerfile personalizado o modificar temporalmente el existente:

```console
$ docker build --target test -t node-docker-image-test .
```

### Ejecutar pruebas en un contenedor de pruebas dedicado

El enfoque recomendado es utilizar el servicio de pruebas definido en `compose.yml`:

```console
$ docker compose --profile test up app-test --build
```

O ejecutarlo como un contenedor de un solo uso:

```console
$ docker compose run --rm app-test
```

### Ejecutar pruebas con cobertura en CI/CD

Para la integración continua, puedes ejecutar las pruebas con cobertura:

```console
$ docker build --target test --progress=plain --no-cache -t test-image .
$ docker run --rm test-image npm run test:coverage
```

Deberías ver una salida que contenga lo siguiente:

```console
 ✓ src/server/__tests__/routes/todos.test.ts (5 tests) 16ms
 ✓ src/shared/utils/__tests__/validation.test.ts (15 tests) 6ms
 ✓ src/client/components/__tests__/LoadingSpinner.test.tsx (8 tests) 67ms
 ✓ src/server/database/__tests__/postgres.test.ts (13 tests) 136ms
 ✓ src/client/components/__tests__/ErrorMessage.test.tsx (8 tests) 127ms
 ✓ src/client/components/__tests__/TodoList.test.tsx (8 tests) 147ms
 ✓ src/client/components/__tests__/TodoItem.test.tsx (8 tests) 218ms
 ✓ src/client/__tests__/App.test.tsx (13 tests) 259ms
 ✓ src/client/components/__tests__/AddTodoForm.test.tsx (12 tests) 323ms
 ✓ src/client/hooks/__tests__/useTodos.test.ts (11 tests) 569ms

 Test Files  9 passed (9)
      Tests  88 passed (88)
    Start at  20:57:19
    Duration  4.41s (transform 1.79s, setup 2.66s, collect 5.38s, tests 4.61s, environment 14.07s, prepare 4.34s)
```

## Resumen

En esta sección, aprendiste cómo ejecutar pruebas al desarrollar localmente usando Docker Compose y cómo ejecutar pruebas al construir tu imagen.

Información relacionada:

- [Referencia de Dockerfile](/reference/dockerfile/) – Comprende todas las instrucciones y sintaxis de Dockerfile.
- [Mejores prácticas para escribir Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Escribe Dockerfiles eficientes, mantenibles y seguros.
- [Referencia del archivo Compose](/compose/compose-file/) – Conoce la sintaxis completa y las opciones disponibles para configurar servicios en `compose.yaml`.
- [Referencia de CLI de `docker compose run`](/reference/cli/docker/compose/run/) – Ejecuta comandos puntuales en un contenedor de servicio.

## Pasos siguientes

A continuación, aprenderás cómo configurar un pipeline de CI/CD utilizando GitHub Actions.

