Hacia un testing honesto: Implementando Gates de Cobertura en CI
En el desarrollo de TuTiendaWeb, hemos alcanzado un hito crucial: la finalización de nuestra Fase 5 de testing. El objetivo principal no era solo aumentar números, sino garantizar que nuestras métricas de calidad en CI fueran una representación fiel de la salud del sistema.
El problema de las métricas 'aspiracionales'
Durante mucho tiempo, nuestro archivo vitest.config.ts declaraba umbrales de cobertura que no se aplicaban de forma estricta. Teníamos una falsa sensación de seguridad: los tests unitarios pasaban, pero el proceso de integración continua no bloqueaba despliegues con código nuevo sin pruebas, o peor aún, ignoraba que gran parte de nuestra lógica crítica de negocio (como servicios de integración) no estaba siendo instrumentada por el ejecutor de pruebas unitarias.
La estrategia de 'Gate Honest'
En lugar de perseguir un 100% de cobertura inalcanzable, decidimos implementar un "gate honesto". Ajustamos nuestra configuración para que los umbrales reflejaran la realidad del código que realmente puede ser validado en el runner unitario, como nuestros esquemas de validación y utilidades puras:
// vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: 'v8',
include: ['src/utils/**', 'src/schemas/**'],
thresholds: {
statements: 95,
branches: 90,
},
},
},
});
Al mover la lógica de integración y E2E a sus propios flujos, evitamos que los resultados se diluyeran. Ahora, cada capa del sistema tiene su propio nivel de exigencia, lo que nos permite detectar regresiones de forma determinista.
Determinismo y control
Uno de los mayores retos fue eliminar la fragilidad en los tests de utilidades de tiempo. Utilizamos vi.useFakeTimers para asegurar que las reglas de negocio, como los horarios de apertura y cierre, se comporten igual independientemente de cuándo o dónde corra el CI:
import { vi, describe, it, expect } from 'vitest';
describe('Validación de horarios', () => {
it('debe identificar correctamente el estado fuera de servicio', () => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2026-06-23T23:00:00'));
expect(isStoreOpen()).toBe(false);
vi.useRealTimers();
});
});
La Lección
La cobertura es una herramienta, no un objetivo. Un gate que falla cuando debería fallar es mucho más valioso que uno que siempre está en verde porque no está configurado correctamente. La calidad de nuestro CI ahora es un reflejo transparente de nuestra confianza en el código.
Acciones para tu próximo sprint:
- Audita tus umbrales: ¿Están basados en lo que realmente estás probando o son solo números arbitrarios?
- Aísla tus capas: No intentes medir la cobertura de toda tu aplicación con una sola herramienta si tu arquitectura separa lógica de negocio de servicios externos.
- Automatiza el bloqueo: Asegúrate de que tu pipeline de CI sea estricto; si el umbral baja, la integración debe fallar inmediatamente.
Generated with Gitvlg.com