Developer tools: cómo testar respuestas de una API de datos antes de comprometer la integración
Developer tools: cómo testar respuestas de una API de datos antes de comprometer la integración
Hay un momento en cada integración en el que el equipo asume que la API se comporta como dice la documentación. Ese momento es el origen de la mayoría de los incidentes en producción. La documentación describe el caso feliz. El dato real, no.
Testar una API de datos no es hacer un curl y ver que devuelve 200. Es verificar que el contrato semántico se cumple: que los campos que promete vienen siempre, con el tipo correcto, en el rango esperado, y que los casos límite no rompen el pipeline. Hacerlo antes de comprometer la integración ahorra semanas de depuración posterior.
Esta guía es para equipos técnicos que consumen APIs de datos externos —señales, menciones, tendencias, análisis derivado— y necesitan un protocolo de validación antes de llegar a producción.
Por qué el 200 OK no es suficiente
Una API puede responder 200 OK con un cuerpo vacío, con campos nulos donde prometía valores, con timestamps en formato inconsistente o con arrays que en edge cases devuelven un objeto en lugar de una lista. Todo eso es un 200 OK que rompe el pipeline.
El primer error de muchos integradores es confiar en el código de estado HTTP como proxy de la calidad del dato. No lo es. El segundo error es testar solo con los parámetros más simples de la query. Las APIs de datos tienen comportamientos distintos según el volumen de resultados, el rango temporal o la combinación de filtros activos.
Un protocolo de testing robusto tiene que cubrir, como mínimo, tres dimensiones: la estructura del esquema, la consistencia semántica y el comportamiento bajo condiciones límite.
Paso 1: construir un schema contract test
Antes de escribir una sola línea de código de integración, define el contrato esperado. Herramientas como JSON Schema o librerías tipo jsonschema en Python permiten describir exactamente qué estructura esperas y validar cada respuesta contra ella de forma automática.
import jsonschema
import requests
schema = {
"type": "object",
"required": ["id", "published_at", "source", "sentiment_score"],
"properties": {
"id": {"type": "string"},
"published_at": {"type": "string", "format": "date-time"},
"source": {"type": "string"},
"sentiment_score": {"type": "number", "minimum": -1, "maximum": 1}
}
}
response = requests.get("https://api.example.com/v1/signals", params={"q": "climate"})
data = response.json()
for item in data.get("results", []):
jsonschema.validate(instance=item, schema=schema)
Ejecuta esto contra respuestas reales, con queries reales. No uses fixtures sintéticos en esta fase: el punto es descubrir lo que la API hace de verdad, no lo que tu fixture simula.
Paso 2: cubrir los edge cases que la documentación ignora
La documentación documenta el happy path. El testing tiene que cubrir lo que la documentación omite.
Queries sin resultados. ¿Qué devuelve la API cuando no hay datos para el rango temporal pedido? ¿Un array vacío, un null, un error 404, o simplemente omite el campo results? Tu pipeline tiene que saberlo antes de asumir.
Volumen máximo por página. Si el límite de paginación es 100 ítems, ¿qué pasa cuando el resultado exacto es 100? ¿Hay siguiente página o no? Algunas APIs devuelven has_more: true incluso en el último bloque. Otras no incluyen el campo si no hay más. Ambas rompen un loop de paginación naive.
Campos opcionales que no siempre vienen. Los campos marcados como "opcional" en la documentación a veces no aparecen en el JSON. No como null, directamente ausentes. Un item["campo"] en Python lanza KeyError. Un .get("campo") devuelve None silenciosamente. La diferencia entre los dos puede costar horas de depuración.
Timestamps y zonas horarias. Una API que devuelve published_at en UTC puede cambiar ese comportamiento según la región de la fuente. Valida siempre que los timestamps tienen zona horaria explícita (Z o +00:00), no asumas.
Paso 3: automatizar los tests de regresión de respuesta
Una vez que defines el contrato y cubres los edge cases, el siguiente paso es no depender de la memoria del equipo para recordar que hay que volver a validar cuando la API lanza una nueva versión.
La solución práctica: un test suite que se ejecuta contra el endpoint real (o un sandbox si el proveedor lo ofrece) de forma periódica. No solo en el momento de la integración, sino como parte del pipeline de CI/CD.
# Ejemplo: GitHub Actions schedule
on:
schedule:
- cron: "0 6 * * 1" # Lunes a las 6 AM
jobs:
api-contract-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run contract tests
run: python -m pytest tests/test_api_contract.py -v
env:
API_KEY: ${{ secrets.FEEDSCALE_API_KEY }}
Esto detecta roturas de contrato antes de que lleguen a producción. Si la API cambia un campo de string a integer en una nueva versión sin aviso —y ocurre, incluso en proveedores maduros—, el test lo captura el lunes por la mañana, no el viernes a las 6 PM.
Paso 4: medir la varianza del dato, no solo la presencia
Una API de análisis de datos como las que expone FeedScale devuelve señales derivadas —sentiment scores, volumen de menciones, clasificaciones temáticas— que tienen una distribución estadística. El testing no termina en verificar que el campo sentiment_score existe y es un número.
El siguiente nivel es verificar que los valores tienen sentido estadístico:
- ¿El score cae consistentemente en el rango documentado?
- ¿La distribución de sentimiento para una query neutral es aproximadamente equilibrada?
- ¿El volumen de resultados para un keyword de alta frecuencia está dentro de un orden de magnitud esperado?
Esto no requiere modelos complejos. Un test simple que alerte si más del 30% de los scores son exactamente 0.0 (señal de que el modelo no está procesando esa categoría de texto) puede detectar problemas de configuración antes de que contaminen el análisis.
Qué hacer cuando el test falla en producción
Los contratos de API fallan en producción. No es una eventualidad, es una certeza estadística si el pipeline tiene suficiente longevidad. El protocolo de testing previo no elimina los fallos, reduce su impacto.
Cuando un test de contrato falla en producción, el sistema necesita tres capacidades: detectar el fallo automáticamente (alertas sobre campos inesperados o ausentes), degradar con gracia (continuar procesando los registros válidos, aislar los inválidos en una cola de cuarentena) y producir un log estructurado que permita reproducir el fallo.
Sin ese log estructurado, el debugging de fallos intermitentes en APIs externas es pura arqueología. Con él, el tiempo de resolución cae de horas a minutos.
El testing de APIs de datos no es una fase del proyecto. Es una práctica continua. Los proveedores evolucionan sus esquemas, las fuentes de datos cambian su comportamiento, y los edge cases emergen con el volumen real. El equipo que trata el contrato de la API como un documento vivo —verificado, monitorizado y versionado— es el que llega al incidente de producción con contexto, no con sorpresa.