Ilustración editorial: Pruebas de Contrato con Pact para Equipos Pequeños: Una Guía Práctica

pruebas de API · pruebas de contrato · Pact · microservicios · QA · automatización

Pruebas de Contrato con Pact para Equipos Pequeños: Una Guía Práctica

Aprende cuándo y cómo adoptar pruebas de contrato dirigidas por el consumidor con Pact. Una guía práctica para desarrolladores independientes y equipos pequeños que buscan confiabilidad en APIs sin sobrecarga empresarial.

Publicado:

Deje de Romper las APIs de los Demás

Si alguna vez ha enviado un cambio pequeño a una API: renombró un campo, hizo que un valor opcional fuera requerido, ajustó un código de estado, y vio cómo su servicio consumidor se rompía en producción, conoce el dolor que las pruebas de contrato existen para resolver. Sus propias pruebas estaban verdes. Ninguna prueba de integración lo detectó. El fallo surgió demasiado tarde, en un entorno que ninguno de los equipos controlaba, con culpa ambigua.

Las pruebas de contrato invierten este problema. En lugar de levantar ambos servicios y probarlos de extremo a extremo, captura las expectativas exactas que un consumidor tiene de un proveedor como un contrato legible por máquina, luego verifica el proveedor contra ese contrato de forma independiente, en el pipeline de cada equipo. Pact es el framework más utilizado para esto, y funciona bien incluso para equipos pequeños que no pueden permitirse herramientas empresariales o sobrecarga pesada de CI.

Qué Son Realmente las Pruebas de Contrato

Una prueba de contrato no es una prueba unitaria y no es una prueba de integración. Se sitúa entre ambas. El consumidor escribe pruebas contra un mock ligero del proveedor que Pact levanta localmente. Mientras esas pruebas se ejecutan, Pact registra cada solicitud que el consumidor hace y la respuesta que espera. Ese conjunto grabado de interacciones se convierte en el contrato: un archivo JSON que dice, en términos claros: cuando envío esta solicitud, espero esta respuesta.

Separadamente, el proveedor reproduce esas solicitudes grabadas contra su implementación real y verifica que produce respuestas coincidentes. Ningún lado necesita que el otro esté ejecutándose al mismo tiempo. Cada lado prueba en su propio pipeline rápido e aislado. El contrato es el artefacto compartido que los mantiene sincronizados.

Esto es pruebas de contrato dirigidas por el consumidor. El consumidor define las expectativas. El proveedor demuestra que puede cumplirlas. Ambos equipos son responsables de su lado de la verificación.

Pruebas de Contrato vs Pruebas de Integración

El instinto cuando dos servicios deben funcionar juntos es probarlos juntos. Eso funciona, pero escala terriblemente. Con N servicios, el número de combinaciones de integración explota. El entorno es lento y frágil. Un fallo raramente señala claramente qué lado rompió el acuerdo. Peor aún, las pruebas de integración se ejecutan tarde, a menudo solo en un entorno de staging compartido, por lo que la retroalimentación llega mucho después del commit ofensor.

Las pruebas de contrato eliminan la necesidad de que ambos servicios se ejecuten juntos. Te dan retroalimentación rápida a velocidad de prueba unitaria en el propio CI de cada equipo. Te dicen claramente qué lado rompió el contrato. No reemplazan las pruebas de integración; las complementan. Las pruebas de integración verifican que los servicios funcionen juntos en un entorno realista. Las pruebas de contrato verifican que la interfaz de API en sí permanezca compatible. Necesitas ambos, pero resuelven problemas diferentes.

Aspecto Pruebas de Integración Pruebas de Contrato (Pact)
Ambos servicios ejecutándose Requerido No requerido
Velocidad de retroalimentación Lenta (staging, tarde) Rápida (velocidad de prueba unitaria)
Qué lado rompió Ambiguo Atribución clara
Complejidad del entorno Alta Baja
Alcance de cobertura Flujos de extremo a extremo Compatibilidad de interfaz de API

Cuándo Adoptar Pruebas de Contrato

Las pruebas de contrato son más valiosas cuando controlas el desarrollo tanto del consumidor como del proveedor, y los requisitos del consumidor impulsan las características del proveedor. Son excelentes para microservicios intra-organizacionales donde dos equipos dentro de la misma organización pequeña necesitan coordinar cambios de API sin pisarse mutuamente.

Son menos útiles para consumidores de API externos que no tienen control sobre la base de código del proveedor. En esos casos, las pruebas basadas en OpenAPI pueden ser más apropiadas. Pact también es excesivo para un solo servicio sin dependencias de API externas, o para APIs CRUD simples donde la superficie es pequeña y los cambios son raros.

Si tu equipo es pequeño y estás construyendo microservicios internos que se comunican entre sí a través de HTTP, las pruebas de contrato valen la inversión. La recompensa es menos incidentes de producción causados por desajustes de API y retroalimentación más rápida cuando esos desajustes ocurren.

Una Implementación Mínima

No necesitas un Pact Broker ni PactFlow para comenzar. Puedes empezar con archivos pact locales y verificarlos manualmente. Aquí hay un flujo de trabajo mínimo usando Pact en Python con pytest.

Paso 1: El Consumidor Escribe las Expectativas

Instala la biblioteca Pact para Python. Escribe una prueba que defina lo que tu servicio espera del proveedor. Usa fixtures de pytest para configurar el proveedor mock. Especifica el método de solicitud, ruta, encabezados y el cuerpo de respuesta esperado con código de estado.

import pytest
from pact import Consumer, Provider

@pytest.fixture
def api_contract():
    consumer = Consumer('mi-servicio')
    provider = Provider('servicio-usuarios')
    return consumer.has_pact_with(provider, pact_url='pacts/')

def test_get_user_retorna_formato_esperado(api_contract):
    api_contract.given('usuario existe').upon_receiving('una solicitud para usuario 1').will_respond_with(
        200,
        headers={'Content-Type': 'application/json'},
        body={'id': 1, 'name': 'Juan Pérez', 'email': 'juan@ejemplo.com'}
    )
    # Realiza la solicitud real contra el proveedor mock
    response = requests.get('http://localhost:1234/usuarios/1')
    assert response.status_code == 200
    assert response.json()['name'] == 'Juan Pérez'

Paso 2: Ejecuta las Pruebas del Consumidor

Ejecuta las pruebas del consumidor. Pact genera un archivo pact—un contrato JSON—en disco. Inspecciónalo. Deberías ver las interacciones que definiste, con matching de solicitudes y expectativas de respuesta. Este archivo es tu artefacto. Compártelo con el equipo del proveedor.

Paso 3: El Proveedor Verifica contra el Contrato

El equipo del proveedor configura la verificación de Pact en su pipeline. Lo apunta al archivo pact y ejecuta la verificación contra su implementación real. Si el proveedor devuelve una respuesta que no coincide con el contrato, la verificación falla. El equipo del proveedor corrige su código o negocia un cambio de contrato con el equipo del consumidor.

Paso 4: Comparte los Contratos

Una vez que tienes un flujo de trabajo local funcionando, considera publicar contratos en un Pact Broker o usar el servicio hospedado PactFlow. Esto te da una única fuente de verdad y habilita verificación automatizada a través de pipelines. También puedes usar verificaciones can-i-deploy para proteger lanzamientos de forma segura—verificando que un consumidor es compatible con el proveedor antes de que cualquiera de los dos envíe.

Errores Comunes a Vigilar

Los contratos no son un sustituto de la buena comunicación entre equipos. Si los equipos del consumidor y del proveedor no hablan, las pruebas de contrato no te salvarán. El contrato captura lo que el consumidor espera, pero no captura la intención. La ambigüedad en el diseño de la API se manifestará como fricción en el proceso de contrato.

Los estados del proveedor pueden volverse complejos. Si tu proveedor tiene múltiples estados—usuario existe, usuario no existe, usuario está suspendido—necesitas configurar los datos correctos para cada estado antes de que se ejecute la verificación. Esto añade sobrecarga. Comienza simple. Añade estados solo cuando sea necesario.

No codifiques archivos pact a mano ni los generes desde Swagger. El propósito del archivo pact es mantener las pruebas en ambos proyectos sincronizadas. Si lo generas desde algo diferente a las pruebas del consumidor, defeats el propósito. El contrato debe ser impulsado por el comportamiento real del consumidor.

Cuándo No Hacerlo

Omite las pruebas de contrato si estás construyendo un solo servicio sin dependencias de API externas. Omítelo si tu superficie de API es pequeña y los cambios son raros. Omítelo si tu equipo no tiene desarrolladores que puedan escribir las pruebas—Pact es code-first y requiere comprensión del código bajo prueba, cómo escribir pruebas, cómo usar bibliotecas de prueba, y cómo crear e inyectar stubs. Los testers sin experiencia sólida en codificación tendrán dificultades. Emparejalos con desarrolladores.

También omítelo si estás sirviendo consumidores de API externos que no comparten tu base de código. Las pruebas basadas en OpenAPI son más apropiadas allí. Pact está diseñado para microservicios intra-organizacionales donde controlas ambos lados de la integración.

FAQ

¿Todavía necesito pruebas de integración si uso Pact? Sí. Las pruebas de contrato verifican la compatibilidad de la interfaz de API. Las pruebas de integración verifican que los servicios funcionen juntos en un entorno realista. Responden preguntas diferentes. Usa ambos.

¿Puedo usar Pact con servicios que no sean Python? Pact tiene bibliotecas para muchos lenguajes. El archivo de contrato es JSON agnóstico al lenguaje. Puedes escribir pruebas de consumidor en Python y verificarlas contra un proveedor escrito en Go, Node, o cualquier otra cosa.

¿Es PactFlow requerido? No. Puedes comenzar con archivos pact locales y compartirlos manualmente. PactFlow añade valor cuando necesitas publicación centralizada de contratos, versionado, y verificaciones can-i-deploy a través de múltiples pipelines.

¿Quién debe escribir las pruebas Pact? Desarrolladores. Pact es code-first y requiere comprensión del código bajo prueba, cómo escribir pruebas, cómo usar bibliotecas de prueba, y cómo crear e inyectar stubs. Los testers sin experiencia en codificación deben emparejarse con desarrolladores.

Qué es un provider state? Un provider state describe la condición del proveedor antes de que se haga una solicitud. Por ejemplo, “usuario existe con ID 1” o “usuario no existe”. El equipo del proveedor escribe código para configurar los datos correctos para cada estado antes de que se ejecute la verificación.

Conclusiones Clave

Las pruebas de contrato con Pact dan a los equipos pequeños una forma práctica de prevenir roturas de API sin la sobrecarga de herramientas empresariales. Invierten el problema de las pruebas de integración: en lugar de probar ambos servicios juntos en un entorno lento, pruebas cada lado de forma independiente contra un contrato compartido. La retroalimentación es rápida. La culpa es clara. El flujo de trabajo es ligero.

Comienza simple. Escribe pruebas de consumidor que generen archivos pact. Comparte esos archivos con el equipo del proveedor. Verifícalos en el pipeline del proveedor. Añade un Pact Broker solo cuando necesites gestión centralizada de contratos. Y nunca olvides que los contratos son una herramienta de comunicación, no un reemplazo para hablar entre ustedes.

Fuentes