EGEL Plus Ingeniería de Software study materials
EGEL Plus Ingeniería de Software study resources

Cobertura alta, defectos en producción: qué probar en un servicio de pagos

EGEL Plus Ingeniería de Software · Put your knowledge to work in context.

All case studies

Cobertura alta, defectos en producción: qué probar en un servicio de pagos

Un servicio de pagos tiene 87% de cobertura de líneas y 0 pruebas de integración. En el último trimestre, 6 de 9 incidentes en producción provinieron de interacciones entre el servicio y la pasarela externa: respuestas 200 con cuerpo de error, timeouts de 30 s tratados como éxito y webhooks duplicados que generaron doble cargo. Las pruebas unitarias mockean la pasarela con respuestas ideales. El equipo propone 'subir la cobertura al 95%' como remedio. El líder técnico pide un plan alternativo antes de la próxima release, con presupuesto de 2 sprints y sin acceso a un entorno real de la pasarela (solo un sandbox que a veces devuelve 500).

1. Evalúa la propuesta de subir la cobertura al 95%. ¿Por qué no ataca los incidentes observados?

Read the worked answer

La cobertura mide ejecución, no verificación de comportamiento en fronteras. Con 87% ya se ejecutan casi todas las líneas; los fallos viven en contratos que los mocks simplifican:

  • El mock siempre devuelve 200 con cuerpo válido → nunca se prueba '200 con cuerpo de error', que es un caso real del proveedor.
  • El mock responde al instante → el timeout de 30 s y su tratamiento como éxito no se ejercitan.
  • El mock no reenvía webhooks → la idempotencia no se prueba.

Subir al 95% añadiría líneas triviales (getters, ramas de logging) sin tocar estas fronteras. Es una métrica de vanidad en este contexto.

Reencuadre: el objetivo no es cobertura, es riesgo cubierto. Los 6 incidentes definen exactamente qué probar: contrato de respuesta, semántica de timeout, idempotencia de webhooks.

2. Diseña el conjunto de pruebas que habría detectado los 6 incidentes, dado que solo hay sandbox inestable.

Read the worked answer

1. Pruebas de contrato (consumer-driven):

  • Grabar respuestas reales del sandbox (incluidas 200 con status:error, cuerpos truncados, null) y reproducirlas con un stub local determinista.
  • Verificar que el servicio solo trata como éxito el código de negocio esperado, no el HTTP 200.

2. Pruebas de timeout y resiliencia:

  • Stub que retrasa 31 s → aserción: se aborta, se marca unknown y no se confirma el cargo.
  • Stub que devuelve 500 intermitente → verificar reintento con backoff y tope.

3. Idempotencia de webhooks:

  • Enviar el mismo evento dos veces con el mismo event_id → aserción: un solo cargo, segunda respuesta 200 idempotente.
  • Enviar eventos fuera de orden → estado consistente.

4. Pruebas de integración contra sandbox en pipeline nocturno, tolerantes a 500 (marcar skip y alertar, no fallar el build), para detectar deriva del proveedor.

Criterio de éxito: cada uno de los 6 incidentes se reproduce como prueba que falla antes del fix y pasa después (prueba de regresión).

3. Con 2 sprints y sandbox inestable, prioriza. ¿Qué dejas fuera y cómo justificas el riesgo residual?

Read the worked answer

Sprint 1 (mayor impacto):

  • Contrato de respuesta (cubre '200 con error').
  • Timeout → estado unknown con reconciliación posterior (cubre el doble cargo por timeout tratado como éxito).
  • Idempotencia por event_id en webhooks (cubre el doble cargo por duplicados).

Estos tres cubren 6/6 incidentes conocidos.

Sprint 2:

  • Suite de integración nocturna contra sandbox con tolerancia a fallos.
  • Reconciliación automática de pagos en estado unknown.

Fuera de alcance: subir cobertura al 95%, fuzzing exhaustivo, pruebas de carga de la pasarela. No reducen el riesgo observado en el plazo.

Riesgo residual declarado: el sandbox no reproduce todos los comportamientos del proveedor; podría aparecer un modo de fallo nuevo. Mitigación: telemetría de respuestas no reconocidas en producción y alerting cuando aparezca un código de negocio no mapeado. Se acepta el riesgo con vigilancia, no en silencio.