Unit vs Integration Tests
1) Por qué distinguir entre los tipos de pruebas
La granulación correcta de las pruebas hace que el desarrollo sea predecible: Unit captura los defectos de la lógica de forma rápida y barata; La integración comprueba los conjuntos de módulos, el transporte real y el «pegamento». Juntos, reducen la regresión y aceleran las liberaciones.
2) Definiciones y límites
Prueba de unidad
Comprueba una pequeña unidad de comportamiento (función, clase, caso de uso) en aislamiento.
Las dependencias externas son reemplazadas (mock/stub/fake).
Rápido (ms-decenas de ms), determinista.
Prueba de integración
Comprueba la interacción de varios componentes reales: DAB, bróker (Kafka/RabbitMQ), HTTP/gRPC, sistema de archivos, caché.
Un mínimo de mokas, protocolos reales.
Más lento (cientos de ms-segundos), más caro en soporte.
3) Prueba de pirámide (no cuerno de hielo)
Base: Unidad (70-80% en cantidad) - barato, rápido.
Capa media: Integración/Composición (15-25%) - Rutas y contratos críticos.
Top: E2E/UX/Exploratory (5-10%) - mínimamente suficiente.
A los lados: Análisis estadístico/Control de tipo/Enlace y Prueba de mutación como amplificadores de calidad.
4) Qué dar a la Unidad, y qué - Integración
5) Datos y fixtures
Unit
Fixtures/builders en línea (methods de fábrica).
Pruebas tabulares (table-driven) para valores límite.
Un enfoque basado en propiedades para invariantes (por ejemplo, «suma de adeudos = suma de créditos»).
Integration
Entorno hermético: Testcontainers/Docker Compose elevan 'postgres + redis + kafka + wiremock'.
Semilla inicial en el CD/caché y limpieza después (transacción/rollback, truncate).
Relojes/temporizadores - falsos (controlados), de lo contrario, flakes.
6) Herramientas y patrones
Mocks/Stubs/Fakes/Spies:- Stub es una respuesta fija (barata).
- Mock: comprueba las interacciones/el número de llamadas.
- Fake es una implementación simplificada (por ejemplo, In-Memory Repo).
- Prueba de contratos (CDC): Nat/Swagger-based - Registramos las expectativas del cliente y verificamos al proveedor.
- WireMock/MockServer - enchufes HTTP para servicios de terceros.
- Testcontainers - DB en vivo/brokers localmente y en CI sin «zoológico».
7) Ejemplos
7. 1 Unidad: idempotencia de pago (pseudocode)
python def test_idempotent_create_payment_returns_same_id():
repo = InMemoryPayments()
service = Payments(repo)
first = service. create(amount=100, key="abc")
second = service. create(amount=100, key="abc")
assert first. id == second. id assert repo. count() == 1
7. 2 Integración: firma de webhook (HMAC) + repetición
bash docker-compose: app + redis + wiremock (PSP)
docker compose -f docker-compose. test. yml up -d pytest -m "integration and webhook" -q
Prueba:
- WireMock regala el evento con 'X-Timestamp' y la firma.
- La aplicación comprueba el HMAC, deduplica por 'event _ id', la repetición después de 5 segundos no crea una toma.
- Comprobamos '200' y que el registro es uno.
7. 3 CDC: contrato del cliente con el proveedor
El cliente formará un Nat (pendiente: 'POST/v1/payout' → '201' con el esquema).
El proveedor de CI ejecuta la verificación del contrato en su stand.
8) Velocidad, paralelismo, Flakes
La unidad debe trabajar <100 ms por prueba; Paquete - segundos.
Integración - Paralela por contenedor/puerto; utilizar migraciones en el inicio.
- tiempo controlado (fake clock),
- expectativas «sobre un evento explícito», en lugar de 'sleep',
- umbrales estables (retraídas con jitter para probar deterministamente).
9) Métricas de calidad
Coverage (líneas/ramas): útil para observar la tendencia, pero no el objetivo.
Mutation testing (PIT/Mutmut): muestra si las pruebas «matan» los falsos cambios - el poder real del assurence.
Prueba de duración y tasa de flaky: alertas en crecimiento.
Contenido definido: proporción de errores interceptados antes de la producción.
10) Incrustación en CI/CD
Jobs: unit → integration → e2e (fan-out por servicios).
Caché de dependencias, matrices paralelas por BD/idiomas/versiones.
Informes: AMBnit/Allure + artefactos de registros de contenedores (en caídas).
Puerta: «unidad verde + integración crítica» - condición de merluza; e2e - nightly.
yaml strategy:
matrix:
db: [postgres14, postgres16]
steps:
- run: docker run -d --name db -e POSTGRES_PASSWORD=pw postgres:${{ matrix. db }}
- run: pytest -m "unit" -q
- run: pytest -m "integration" -q
11) Microservicios y eventos
Contratos de servicio: OpenAPI/Protobuf se versionan; pruebas de compatibilidad (backward).
Event-driven:- Unidad: mapping eventos de dominio e invariantes.
- Integración: publicación/suscripción en un corredor real (Kafka), outbox/inbox semántica, exactly-once imitación (al menos - idempotent).
- Pruebas de retraídas/duplicados/reordenación (fuera de orden).
12) Datos y aislamiento en Integración
Cada prueba → un circuito/DAB único (Testcontainers JDBC URL '? TC _ TMPFS =/var/amb/postgresql/data: rw').
Los fixtures transaccionales (begin→run→rollback) aceleran la limpieza.
Para Redis/caché, el prefijo clave es 'test: $ {RUN _ ID}:' y 'FLUSHDB' en teardown.
13) Especificidad de iGaming/finanzas
Dinero y límites: pruebas de invariantes basadas en propiedades (balance ≥ 0, restricciones totales).
Regulación: comprobación de registro (auditoría-registro escrito), eventos inmutables.
Pagos/PSP: pruebas de integración HMAC/mTLS, 'Retry-After', idempotencia, dedoup 'jti'.
Juego responsable: pruebas de reglas de umbrales/couldowns; «vchera→segodnya» en fake clock.
14) Antipattern
La «unidad» que levanta el BD/NTTR es ya la integración (confunde las capas y ralentiza el CI).
Alta cobertura a expensas de afirmaciones en blanco («cubierto, pero no verificado»).
Moki de la lógica de los servicios de terceros donde se necesita un contrato (se rompe cuando se actualiza).
Pruebas con 'sleep (5)' en lugar de expectativas de eventos/condiciones.
DAB de prueba común para pruebas paralelas → carreras y flautas.
15) Lista de comprobación prod
- Pirámide definida:% de la proporción de Unit/Integration/E2E y objetivos según el tiempo de ejecución.
- La unidad está aislada, es rápida, cubre valores límite e invariantes.
- La integración utiliza un entorno hermético (Testcontainers/Compose), sin estates comunes.
- Las pruebas contractuales (OpenAPI/Nat) se verifican en CI.
- Los datos de las pruebas son manejables: seed/rollback/prefijos, fake clock.
- Ejecución paralela, reportes de AMBnit/Allure, artefactos de registros de contenedores.
- Métricas: duración, tasa de flaky, puntuación de mutación; alertas de degradación.
- Escenarios de pago/webhook: HMAC/mTLS, retraídas, idempotencia, dedoop.
- Documentación de estrategia y plantillas de prueba de ejemplo.
16) TL; DR
Unidad - máxima lógica, mínimo entorno; La integración es un mínimo de mocos, un máximo de realismo. Mantenga la pirámide: Unidades rápidas atrapan el 80% de los defectos, Integración confirma ligamentos y contratos. Use contenedores herméticos, pruebas contractuales, clock fake y paralelismo. Medir no sólo coverage, sino también mutation score y flaky rate. Compruebe especialmente las rutas de pago/webhook: firmas, retraídas e idempotencia.