Análisis de Cobertura de Tests PR #147

marta.ruiz@flowmetrics.io feature/proration-engine → main 18 jun 2026 3 archivos · +236 / −55 líneas
62
Test Score
Necesita mejoras
62%
Cobertura comportamiento
3
Brechas críticas
4
Brechas importantes
3
Tests correctos
Cobertura por archivo
app/billing/subscription.py 58%
app/billing/webhooks.py 15%
tests/billing/test_subscription.py 100%
Brechas críticas
Crítico
Sin test para days_remaining=0 en ProrationEngine
calculate_proration lanza ValueError si days_remaining <= 0 pero no existe ningún test que verifique este comportamiento. En producción, un downgrade en el último día del ciclo causaría un 500 no manejado.
# Test faltante sugerido def test_calculate_proration_zero_days_raises(): engine = ProrationEngine() with pytest.raises(ValueError, match="days_remaining must be > 0"): engine.calculate_proration(plan_a, plan_b, days_remaining=0)
subscription.py:8
Crítico
Webhook de Stripe sin ningún test unitario ni de integración
El handler handle_stripe_event en webhooks.py gestiona fallos de pago y cancelaciones, pero no tiene ni un solo test. La verificación de firma Stripe (SignatureVerificationError), el flujo de invoice.payment_failed y el de customer.subscription.deleted están completamente sin cubrir.
webhooks.py:1–45
Crítico
apply_proration no tiene test de integración con DB mock
apply_proration llama a _charge_customer y _credit_customer y muta el objeto subscription, pero no hay ningún test que verifique que la base de datos se actualiza correctamente ni que la mutación del estado se persiste. Un fallo silencioso aquí podría cobrar sin actualizar el plan del cliente.
# Test faltante sugerido def test_apply_proration_upgrade_charges_and_updates_plan(mocker): engine = ProrationEngine() mock_charge = mocker.patch.object(engine, '_charge_customer') sub = make_subscription(plan='basic', days_left=15) result = engine.apply_proration(sub, new_plan=pro_plan) mock_charge.assert_called_once() assert sub.plan == pro_plan assert result["status"] == "ok"
subscription.py:21–32
Brechas importantes
Importante
Grace period de cancelación no probado end-to-end
Se añadió el flujo pending_cancellation con cancel_at = now + 7 días, pero solo existe el test de cancelación inmediata. Falta verificar que el estado queda en pending_cancellation y que cancel_at tiene la fecha correcta.
subscription.py:36–42
Importante
Aserciones débiles: assert result > 0 no valida el importe exacto
test_calculate_proration_upgrade y test_calculate_proration_downgrade solo comprueban el signo del delta, no el valor aritmético. Si la fórmula cambia (ej. ciclo de facturación distinto a 30 días), el test no detectaría la regresión.
test_subscription.py:8–18
Importante
Ciclo de facturación personalizado (billing_cycle != 30) sin test
El parámetro billing_cycle admite valores distintos a 30 pero nunca se prueba. Clientes con ciclos anuales (365 días) obtendrían cálculos incorrectos sin que los tests lo detecten.
subscription.py:6
Importante
Firma Stripe inválida — ruta de error 400 sin test
El bloque try/except SignatureVerificationError devuelve HTTP 400, pero ningún test simula una firma inválida. Un refactor del handler podría romper la validación sin advertencia.
webhooks.py:8–12
Sugerencias de mejora
🛠
Fijar valores exactos en aserciones aritméticas. Reemplazar assert result > 0 por assert result == Decimal("25.00") (calculado manualmente). Esto convierte los tests en especificación ejecutable de la fórmula.
🏭
Crear tests/billing/test_webhooks.py con fixtures de eventos Stripe. Usar stripe.util.convert_to_stripe_object o JSON fixtures para simular payloads y verificar la lógica de dispatch sin llamadas reales a la API.
📋
Parametrizar TestProrationEngine con @pytest.mark.parametrize para cubrir combinaciones de planes, days_remaining (1, 15, 29, 30) y billing_cycle (30, 365) en una sola definición de test.
📍
Añadir nombres descriptivos a los tests de cancelación. test_cancel_subscription_grace_period_sets_pending_status es más informativo que test_cancel_not_immediate y facilita el diagnóstico de fallos en CI.
Aspectos positivos
Separación de casos happy path bien hecha. Los tests test_calculate_proration_upgrade y test_calculate_proration_downgrade cubren los dos flujos principales de la clase ProrationEngine de forma clara y aislada.
Test de cancelación inmediata correcto. test_cancel_subscription_immediate verifica el estado resultante del objeto, no solo que no lanza excepción. Buen patrón de aserción a seguir en el resto.
Estructura de test coherente con la arquitectura del proyecto. Los tests están correctamente ubicados en tests/billing/, espejando la estructura de app/billing/, lo que facilita la navegación y el mantenimiento.