Cuando un equipo de backend renombra un campo de respuesta, los tests E2E en staging lo detectan después del despliegue. El contract testing lo detecta antes: el frontend genera un contrato formal a partir de sus propios tests, y el backend verifica que puede satisfacer esas expectativas de forma independiente, sin correr el suite de integración completo. Esta guía cubre Pact para el contract testing orientado al consumidor en un stack TypeScript, desde generar un archivo pact hasta ejecutar la verificación del proveedor en CI.
Qué es el contract testing
El contract testing verifica que dos servicios están de acuerdo en el formato de su comunicación, no solo que cada servicio funciona correctamente por sí solo.
Un contrato es una descripción formal de lo que un consumidor (tu frontend u otro servicio) espera de un proveedor (tu API). El consumidor genera el contrato a partir de sus propios tests. El proveedor verifica que puede satisfacer esas expectativas sin correr el suite completo de tests del consumidor.
El resultado: detectas los cambios que rompen la API antes de que lleguen a staging.
Pact: la herramienta estándar
Pact es la librería de contract testing más adoptada. Funciona registrando interacciones reales de la API durante los tests del consumidor, guardándolas como "pacts" (archivos JSON) y reproduciéndolas contra el proveedor real.
Instalación del lado del consumidor (frontend)
npm install -D @pact-foundation/pactEscribir un test del consumidor
Este test define lo que tu frontend espera del endpoint /users/1:
import { PactV3, MatchersV3 } from '@pact-foundation/pact';
import path from 'path';
const { like, string, integer } = MatchersV3;
const provider = new PactV3({
consumer: 'frontend',
provider: 'user-api',
dir: path.resolve(process.cwd(), 'pacts'),
});
describe('Contrato de la API de usuarios', () => {
it('devuelve los datos del usuario', async () => {
await provider
.given('el usuario 1 existe')
.uponReceiving('una solicitud para el usuario 1')
.withRequest({
method: 'GET',
path: '/users/1',
headers: { Authorization: like('Bearer token123') },
})
.willRespondWith({
status: 200,
headers: { 'Content-Type': 'application/json' },
body: {
id: integer(1),
name: string('Alice'),
email: string('alice@example.com'),
},
})
.executeTest(async (mockServer) => {
const response = await fetch(`${mockServer.url}/users/1`, {
headers: { Authorization: 'Bearer token123' },
});
const data = await response.json();
expect(data.name).toBeDefined();
expect(data.email).toBeDefined();
});
});
});Cuando este test corre, Pact:
1. Inicia un servidor mock
2. Registra la interacción (solicitud + respuesta esperada) como un archivo pact en ./pacts/
3. Ejecuta tu test contra el servidor mock
El archivo pact generado es el contrato. Se ve así:
{
"consumer": { "name": "frontend" },
"provider": { "name": "user-api" },
"interactions": [{
"description": "una solicitud para el usuario 1",
"request": { "method": "GET", "path": "/users/1" },
"response": {
"status": 200,
"body": { "id": 1, "name": "Alice", "email": "alice@example.com" }
}
}]
}Verificación del lado del proveedor (backend)
El equipo de backend toma este archivo pact y verifica que su API lo satisface:
import { Verifier } from '@pact-foundation/pact';
describe('Verificación del proveedor', () => {
it('valida las expectativas del Frontend', () => {
return new Verifier({
provider: 'user-api',
providerBaseUrl: 'http://localhost:3001',
pactUrls: [path.resolve(process.cwd(), 'pacts/frontend-user-api.json')],
stateHandlers: {
'el usuario 1 existe': async () => {
// insertar usuario de test en la base de datos
await db.users.create({ id: 1, name: 'Alice', email: 'alice@example.com' });
},
},
}).verifyProvider();
});
});El verificador envía la solicitud registrada al backend real y verifica que la respuesta coincide con el contrato. Si el equipo de backend renombra name a full_name, esta verificación falla antes de que cualquier código llegue a staging.
Dónde encaja Playwright
Playwright maneja el testing de integración E2E. El contract testing maneja la verificación de los límites entre servicios. Se complementan.
En la práctica, los contract tests detectan renombrados de campos, campos eliminados, códigos de estado cambiados e inconsistencias de tipos. Los tests E2E de Playwright detectan problemas de renderizado de UI, fallos en los flujos del usuario y fallos de integración de toda la pila.
No reemplazas los tests de Playwright con contract tests. Usas los contract tests para hacer tus tests de Playwright más rápidos y estables, porque menos fallos E2E provienen de cambios en el formato de la API que deberían haberse detectado antes.
Pact Broker: compartir contratos entre equipos
Cuando el consumidor y el proveedor están en repos separados (común en microservicios), necesitás un lugar central para almacenar y compartir los archivos pact. Pact Broker es la herramienta estándar: open source, autoalojable o disponible como PactFlow (su servicio en la nube).
Los equipos publican los pacts después de que corren los tests del consumidor. Los pipelines del proveedor toman el último pact y verifican antes de desplegar. Esto crea una verificación de dependencias: el proveedor no puede desplegar si rompe el contrato de un consumidor.
Cuándo vale la pena el contract testing
El contract testing agrega trabajo: escribir los tests del consumidor con el DSL de Pact, configurar los handlers de estado del proveedor, mantener un broker. Vale la pena cuando:
- Tienes múltiples apps frontend o servicios llamando a la misma API
- Los cambios en la API rompen frecuentemente a los consumidores downstream
- Estás en una arquitectura de microservicios donde los equipos despliegan de forma independiente
- Tu suite E2E es lento y quieres detectar los fallos de integración antes
Probablemente no vale la pena para un monolito donde el frontend y el backend están en el mismo repo y se despliegan juntos, un equipo de dos personas donde ambos lados los maneja la misma persona, o un proyecto en etapa temprana donde la API cambia demasiado rápido para mantener contratos estables.
Empieza con Playwright para E2E. Agrega contract testing cuando tengas dos servicios desplegados de forma independiente que rompen las suposiciones del otro.
→ See also: Pruebas de API con el APIRequestContext de Playwright (Sin Postman) | API Testing 101: Todo lo que Todo QA Engineer Necesita Saber en 2026 | La Pirámide de Tests Explicada para Ingenieros QA