Escribir Tests y Documentar la API para Producción

Lectura
20 min~7 min lectura

Concepto clave

Escribir tests y documentar una API para producción son dos pilares fundamentales que transforman un proyecto de desarrollo en un producto profesional. Imagina que estás construyendo un puente: los tests son las pruebas de carga y estrés que garantizan que la estructura soportará el tráfico real, mientras que la documentación es el manual de mantenimiento y las señales de tráfico que permiten a otros ingenieros entender y utilizar el puente de forma segura. En el contexto de FastAPI, estas prácticas no son opcionales para entornos de producción; son lo que separa una API funcional de una API confiable y mantenible.

Los tests en FastAPI se centran en verificar que los endpoints responden correctamente bajo diferentes condiciones: datos válidos, datos inválidos, autenticación, autorización y casos límite. La documentación, por otro lado, se genera automáticamente gracias a las capacidades integradas de FastAPI (como OpenAPI y Swagger UI), pero requiere una configuración cuidadosa para ser útil en producción. Juntas, estas prácticas reducen los bugs en producción, facilitan la colaboración en equipos y mejoran la experiencia del desarrollador que consume tu API.

Cómo funciona en la práctica

Para implementar tests y documentación en un proyecto de FastAPI, sigue este flujo paso a paso. Primero, estructura tu proyecto con una carpeta dedicada a tests (por ejemplo, tests/) y configura un entorno virtual con las dependencias necesarias, incluyendo pytest, pytest-asyncio, y httpx para testing asíncrono. Luego, escribe tests que simulen peticiones HTTP a tu API, verificando respuestas, códigos de estado y esquemas de datos. En paralelo, mejora la documentación automática añadiendo descripciones detalladas en los decoradores de rutas, usando modelos Pydantic para validación y documentación de datos, y configurando metadatos del proyecto.

Un ejemplo práctico: supón que tienes un endpoint POST /articles para crear artículos en tu API de gestión de contenidos. Antes de escribir tests, define un modelo Pydantic para el artículo con campos como title, content, y author_id. Luego, escribe un test que envíe una petición con datos válidos y verifique que la respuesta tenga un código 201 y contenga el artículo creado. Para la documentación, añade una descripción en el decorador @app.post y usa el modelo Pydantic como parámetro, lo que generará automáticamente la documentación en Swagger UI. Este proceso asegura que tanto la funcionalidad como la documentación estén alineadas y sean mantenibles.

Codigo en accion

A continuación, un ejemplo funcional de un test para el endpoint de creación de artículos y la configuración de documentación en FastAPI. Este código es copiable y ejecutable en un entorno configurado.

# app/main.py - Configuración de la API y documentación
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional
import uuid

app = FastAPI(
    title="API de Gestión de Contenidos",
    description="Una API profesional para gestionar artículos y contenido, con autenticación y autorización.",
    version="1.0.0",
    openapi_url="/api/v1/openapi.json",
    docs_url="/api/v1/docs",
)

class ArticleCreate(BaseModel):
    title: str
    content: str
    author_id: str
    tags: Optional[list[str]] = None

    class Config:
        schema_extra = {
            "example": {
                "title": "Introducción a FastAPI",
                "content": "FastAPI es un framework moderno...",
                "author_id": "user-123",
                "tags": ["python", "api", "backend"]
            }
        }

articles_db = {}

@app.post(
    "/articles/",
    response_model=ArticleCreate,
    status_code=201,
    summary="Crear un nuevo artículo",
    description="Endpoint para crear un artículo en la base de datos. Requiere autenticación en producción."
)
async def create_article(article: ArticleCreate):
    article_id = str(uuid.uuid4())
    articles_db[article_id] = article.dict()
    return article
# tests/test_articles.py - Tests para el endpoint de artículos
import pytest
from httpx import AsyncClient
from app.main import app

@pytest.mark.asyncio
async def test_create_article_success():
    """Test para crear un artículo con datos válidos."""
    async with AsyncClient(app=app, base_url="http://test") as ac:
        payload = {
            "title": "Test Article",
            "content": "This is a test content.",
            "author_id": "test-author",
            "tags": ["test", "fastapi"]
        }
        response = await ac.post("/articles/", json=payload)
        assert response.status_code == 201
        data = response.json()
        assert data["title"] == "Test Article"
        assert "tags" in data

@pytest.mark.asyncio
async def test_create_article_invalid_data():
    """Test para manejar datos inválidos (falta título)."""
    async with AsyncClient(app=app, base_url="http://test") as ac:
        payload = {
            "content": "Content without title",
            "author_id": "test-author"
        }
        response = await ac.post("/articles/", json=payload)
        assert response.status_code == 422  # Unprocessable Entity por validación de Pydantic

Errores comunes

  • No mockear dependencias externas en tests: Si tu API depende de una base de datos o servicios externos, no uses la base real en tests. En su lugar, usa mocks o bases de datos en memoria (como SQLite para pruebas) para aislar los tests y hacerlos rápidos y confiables. Por ejemplo, mockea la conexión a MongoDB con un cliente de prueba.
  • Documentación genérica o incompleta: Dejar la documentación automática con descripciones por defecto o sin ejemplos hace que sea difícil de usar. Siempre añade summary, description, y ejemplos en modelos Pydantic (usando Config.schema_extra) para claridad.
  • Tests que no cubren casos límite: Escribir tests solo para el "happy path" (datos válidos) deja la API vulnerable a errores en producción. Incluye tests para datos inválidos, errores de autenticación, y límites de tasa (rate limiting) si aplica.
  • Ignorar la configuración de CORS y seguridad en documentación: En producción, la documentación debe reflejar las configuraciones de seguridad, como CORS o autenticación. Asegúrate de que los ejemplos en Swagger UI incluyan headers de autenticación si son requeridos.
  • No versionar la API en la documentación: Si cambias la API, la documentación debe reflejar la versión actual. Usa parámetros como openapi_url y docs_url con rutas versionadas (e.g., /api/v1/docs) para evitar confusiones.

Checklist de dominio

  1. ¿Tienes una suite de tests que cubre al menos el 80% de los endpoints, incluyendo casos de éxito, error y validación?
  2. ¿La documentación automática (Swagger UI) muestra ejemplos reales y descripciones claras para cada operación?
  3. ¿Los tests son independientes y no dependen del estado de una ejecución anterior (usando fixtures de pytest para resetear datos)?
  4. ¿Has configurado la documentación con metadatos del proyecto (título, descripción, versión) y rutas versionadas?
  5. ¿Incluyes tests de integración que simulan interacciones complejas, como autenticación seguida de una operación CRUD?
  6. ¿La documentación refleja los requisitos de seguridad, como esquemas de autenticación (e.g., OAuth2) en los endpoints protegidos?
  7. ¿Ejecutas los tests automáticamente en un pipeline de CI/CD (como GitHub Actions) antes de desplegar a producción?

Implementar Tests y Documentación para un Endpoint de Búsqueda de Artículos

En este ejercicio, extenderás la API de gestión de contenidos añadiendo un endpoint de búsqueda de artículos y asegurándolo con tests y documentación profesional. Sigue estos pasos:

  1. Define un nuevo endpoint: En tu archivo app/main.py, añade un endpoint GET /articles/search que acepte un parámetro de consulta q (para término de búsqueda) y opcionalmente tag (para filtrar por etiqueta). Devuelve una lista de artículos que coincidan con la búsqueda, simulando una base de datos con al menos 5 artículos de ejemplo.
  2. Mejora la documentación: Añade una descripción detallada al decorador del endpoint, incluyendo ejemplos de uso en la documentación automática. Usa modelos Pydantic para la respuesta y parámetros de consulta.
  3. Escribe tests exhaustivos: En tests/test_search.py, crea tests que cubran: búsqueda con término encontrado, búsqueda sin resultados, búsqueda con filtro de etiqueta, y manejo de parámetros inválidos (e.g., q vacío). Usa AsyncClient de httpx para las peticiones.
  4. Verifica la cobertura: Ejecuta los tests con pytest --cov=app y asegúrate de que el endpoint de búsqueda tenga al menos un 90% de cobertura de código. Ajusta los tests si es necesario.
  5. Revisa la documentación generada: Inicia la API localmente y navega a /api/v1/docs para verificar que el nuevo endpoint aparezca con ejemplos claros y sea probado desde la interfaz Swagger UI.

Entrega: Un archivo ZIP con los archivos modificados (app/main.py, tests/test_search.py) y un screenshot de la documentación en Swagger UI mostrando el endpoint de búsqueda.

Pistas
  • Usa el parámetro Query de FastAPI para definir parámetros de consulta con valores por defecto y validación, e.g., q: str = Query(..., min_length=1) para requerir al menos un carácter en la búsqueda.
  • En los tests, simula la base de datos de artículos usando un diccionario global en el archivo de tests o un fixture de pytest que se reinicie antes de cada test para evitar interferencias.
  • Para mejorar la documentación, añade un ejemplo en el modelo de respuesta usando Config.schema_extra o en el decorador con el parámetro responses para mostrar códigos de estado comunes como 200 y 404.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.