Skip to content
GitHub

Testing - Estrategia de Pruebas

Este documento describe el enfoque y patrones de pruebas utilizados en el backend Orchestrator. Cubre pruebas unitarias, pruebas de integración y pruebas de endpoints API utilizando Jest como framework principal de pruebas. La estrategia enfatiza la organización de pruebas orientada al dominio, cobertura integral de la lógica de negocio y verificación del aislamiento multi-tenant.


El sistema utiliza Jest versión 29.6.1 con ts-jest para soporte de TypeScript. El entorno de pruebas está configurado para Node.js con resolución de rutas de módulos personalizada.

La configuración de Jest está definida en orchestrator/jest.orchestrator.config.js.

| Clave de Configuración | Valor | Propósito | | :--------------------- | :------------------------------------- | :-------------------------------------------- | ------------------------------ | | preset | ts-jest | Transformación de TypeScript | | testEnvironment | node | Entorno de ejecución Node.js | | roots | ['<rootDir>/src', '<rootDir>/tests'] | Rutas de descubrimiento de archivos de prueba | | moduleNameMapper | { '^@/(.*)$': '<rootDir>/src/$1' } | Resolución de alias de ruta | | testMatch | ['\\\*_/?(_.)+(spec | test).ts'] | Patrones de archivos de prueba | | setupFiles | ['dotenv/config'] | Carga de variables de entorno |

El alias de ruta TypeScript @/* se mapea a src/*, permitiendo importaciones limpias en todas las pruebas:

import { PayrollService } from "@/domain/payroll/PayrollService";
import { getTenantPool } from "@/lib/db";

Este mapeo está sincronizado entre orchestrator/tsconfig.json y la configuración de Jest.


Las pruebas están organizadas por dominio siguiendo la misma estructura que el código fuente:

flowchart TB
  %% =========================
  %% Estructura del Código
  %% =========================
  subgraph CODE["Estructura del Código"]
    direction TB
    SRC["src/"] --> DOMAIN["domain/"]

    DOMAIN --> PAYROLL["payroll/"]
    DOMAIN --> CONTRACTS["contracts/"]
    DOMAIN --> COA["chart-of-accounts/"]
    DOMAIN --> COMMAND["command/"]
  end

  %% =========================
  %% Estructura de Pruebas
  %% =========================
  subgraph TESTS["Estructura de Pruebas"]
    direction TB
    TESTSDIR["tests/"]

    TESTSDIR --> PTESTS["PayrollService.unit.test.ts<br/>PayrollService.integration.test.ts"]
    TESTSDIR --> CTESTS["ContractHtmlGenerator.unit.test.ts"]
    TESTSDIR --> COATESTS["ChartOfAccountsService.unit.test.ts"]
    TESTSDIR --> STESTS["SessionService.test.ts"]
  end

  %% Relaciones código -> pruebas
  PAYROLL --> TESTSDIR
  CONTRACTS --> TESTSDIR
  COA --> TESTSDIR
  COMMAND --> TESTSDIR

Convenciones de Nomenclatura de Archivos de Prueba

Section titled “Convenciones de Nomenclatura de Archivos de Prueba”
Tipo de PruebaPatrón de NomenclaturaEjemplo
Prueba Unitaria*.unit.test.tsPayrollService.unit.test.ts
Prueba de Integración*.integration.test.tsPayrollService.integration.test.ts
Prueba Genérica*.test.tsSessionService.test.ts

El package.json define scripts de ejecución de pruebas dirigidas en orchestrator\package.json.

ScriptComandoPropósito
npm testSolo pruebas unitariasCiclo de retroalimentación rápida
npm run test:allTodas las pruebasValidación completa
npm run test:unitPruebas unitariasPrueba de lógica aislada
npm run test:integrationPruebas de integraciónIntegración base de datos/servicios
npm run test:domainPruebas específicas de dominioEnfoque en lógica de dominio
npm run test:payrollPruebas de dominio de remuneracionesValidación del motor de cálculo
npm run test:watchModo observadorIteración de desarrollo

Las pruebas unitarias validan métodos individuales de servicios y lógica de negocio en aislamiento. Las dependencias se simulan utilizando las capacidades de mocking de Jest.

flowchart LR
  TC["Caso de Prueba"]

  SUT["Servicio Bajo Prueba (ej.,<br/>ChartOfAccountsService)"]

  REPO["Repositorio Simulado<br/>jest.mock()"]
  DB["Pool de Base de Datos Simulado<br/>jest.mock('@lib/db')"]

  TC -- "llama" --> SUT
  TC -- "verifica comportamiento" --> SUT
  TC -- "verifica interacciones" --> REPO

  SUT -- "usa (simulado)" --> REPO
  SUT -- "usa (simulado)" --> DB

Ejemplo: Prueba Unitaria del Servicio de Plan Contable

La prueba en orchestrator/src/domain/chart-of-accounts/__tests__/ChartOfAccountsService.unit.test.ts demuestra:

  1. Simulación de Dependencias
  • Pool de base de datos simulado en @/lib/db
  • Clase de repositorio simulada con jest.mock()
  1. Prueba de Validación
  • Prueba regla de negocio: códigos de cuenta deben ser numéricos
  • Verifica error lanzado para entrada inválida
  1. Prueba de Lógica de Negocio
  • Prueba regla de eliminación: cuentas con hijos no pueden ser eliminadas
  • Verifica verificaciones en cascada apropiadas
// Mock database pool
jest.mock("@/lib/db", () => ({
getTenantPool: jest.fn().mockReturnValue({
query: jest.fn(),
connect: jest.fn().mockResolvedValue({
query: jest.fn(),
release: jest.fn(),
}),
}),
}));
// Mock repository
jest.mock("../ChartOfAccountsRepository");

Las pruebas de integración verifican interacciones entre servicios, repositorios y la base de datos real. Estas pruebas utilizan bases de datos de prueba temporales para asegurar comportamiento realista.

sequenceDiagram
  participant Suite as "Suite de Pruebas"
  participant BeforeAll as "Hook beforeAll()"
  participant DB as "Base de Datos de Prueba test_acc_xxxxx"
  participant SUT as "Servicio Bajo Prueba"
  participant AfterAll as "Hook afterAll()"

  Suite->>BeforeAll: Inicializar suite de pruebas
  BeforeAll->>DB: Crear base de datos temporal
  BeforeAll->>DB: Ejecutar migraciones de esquema
  BeforeAll->>DB: Sembrar datos de prueba

  loop Para Cada Prueba
    Suite->>SUT: Ejecutar escenario de prueba
    SUT->>DB: Realizar operaciones
    DB-->>SUT: Retornar resultados
    SUT-->>Suite: Retornar respuesta
    Suite->>Suite: Afirmar expectativas
  end

  Suite->>AfterAll: Limpieza
  AfterAll->>DB: Eliminar base de datos temporal

Patrón de Nomenclatura de Base de Datos de Prueba

Section titled “Patrón de Nomenclatura de Base de Datos de Prueba”

Las bases de datos de prueba usan el patrón test_acc_<randomId> como se ve en orchestrator/tests/logs/payroll.test.log:

  • test_acc_80f7ecc6
  • test_acc_5a438ce3
  • test_acc_ae9bb86b

Esto asegura el aislamiento de pruebas y permite la ejecución paralela de pruebas.

Las pruebas de API validan endpoints HTTP, autenticación, autorización y flujos de solicitud de extremo a extremo utilizando supertest.

flowchart TD
    A["Caso de Prueba (supertest)"]
    B[Solicitud HTTP POST<br/>/api/remuneraciones/payroll]

    A -->|"supertest.post()"| B

    subgraph MW[Cadena de Middleware]
        M1[Aplicación HTTPS]
        M2[authenticateToken]
        M3[authorizeRoute]
        M4[Middleware de Auditoría]
        M1 --> M2 --> M3 --> M4
    end

    B --> M1

    subgraph APP[Capa de Aplicación]
        R1[Manejador de Ruta Express]
        S1[Capa de Servicio]
        P1[Capa de Repositorio]
        R1 --> S1 --> P1
    end

    M4 --> R1

    DB[(Base de Datos de Prueba)]

    P1 --> DB
    DB -->|Resultado| P1
    P1 -->|Datos| S1
    S1 -->|Respuesta| R1

    R1 -->|HTTP 200/400/500| A

Las dependencias de prueba en orchestrator/package.json incluyen:

  • supertest: Biblioteca de aserciones HTTP
  • @types/supertest: Definiciones TypeScript
import request from "supertest";
import { app } from "@/app";
it("should authenticate and authorize endpoint", async () => {
const response = await request(app)
.post("/api/remuneraciones/payroll/generar")
.set("Authorization", `Bearer ${validToken}`)
.send({ contractId: "...", period: "..." })
.expect(200);
expect(response.body.success).toBe(true);
});