Idiomaesp
← Volver a proyectos

Uso de pruebas de aceptación para evolucionar de forma segura sistemas de negocio complejos

en4Finance4Finance Logo

Los proyectos pueden alcanzar altos niveles de complejidad en la lógica de negocio, haciendo que las actualizaciones sean arriesgadas y lentas. Contar con un proyecto de pruebas de aceptación es una excelente red de seguridad.

2022⏱️ 4min de lectura
JavaCucumberGroovyJenkins

El desafío: La alta complejidad lleva a un delivery lento

Los sistemas financieros suelen contener una gran cantidad de corner cases; un préstamo puede seguir su calendario de pagos original, pero también puede ser pagado parcialmente, refinanciado, retrasado, reestructurado o entrar en impago.

4Finance contaba con un back-office monolítico en Java que se encargaba de todos los cálculos necesarios para el ciclo de vida completo de un préstamo.

En entornos tan complejos e intrincados como este, incluso los cambios aparentemente sencillos pueden volverse peligrosos. Los desarrolladores dedican un tiempo considerable a validar suposiciones, los ciclos de QA se alargan y los equipos se vuelven naturalmente más cautelosos a la hora de desplegar nuevas versiones.

El reto no consiste únicamente en construir nuevas funcionalidades, sino en hacerlo sin romper años de comportamiento de negocio acumulado.

La mitigación: Pruebas de aceptación iterativas con Cucumber

En 4F el equipo de ingeniería trabajaba con pruebas unitarias, de integración y de aceptación. Sin embargo, la suite de pruebas de aceptación se convirtió en la capa más valiosa, porque representaba de manera cercana la lógica de negocio.

El proyecto de AT era sencillo: una implementación de Cucumber repleta de casos de prueba organizados. El factor clave no era el framework en sí, sino la capacidad de expresar las reglas de negocio como casos ejecutables que pudieran ser entendidos tanto por desarrolladores, ingenieros de QA y expertos de negocio por igual.

Utilizando Gherkin, las pruebas lucían así:

Feature: Client defaults after some instalment was paid

    Background:
        Given a client opens a loan for 300€
        And there are 12 instalments

    Scenario: Client pays all the instalments on time
        When client has paid 12 instalments on time
        Then loan is closed

    Scenario: Client defaults after 6 payments
        Given client has paid 6 instalments on time
        When client defaults on the 7th payment
        Then remaining payment includes penalties

    Scenario: Client defaults after 6 payments and then closes the loan
        Given client has paid 6 instalments on time
        When client defaults on the 7th payment
        And client pays all instalments
        Then loan is close
        

Por debajo del sencillo código Gherkin, había scripts en Groovy que se encargaban de realizar las llamadas a la API y en caso de ser necesario, ejecutar las acciones en el navegador mediante Selenium.

Integrando las Pruebas de Aceptación en el flujo de trabajo

Cada vez que se descubría un error o un corner case, el primer paso solía ser plasmarlo como un escenario de aceptación. Esto creaba un ejemplo reproducible del problema para los desarrolladores, mientras que los ingenieros de QA ampliaban el escenario inicial con variaciones adicionales y casos extremos.

As-Is Architecture: Heavy read load on MongoDB

Dado que tanto el back-office como el proyecto de Cucumber tenian ya cierta madurez, la mayoría de los cambios solo requerían añadir o actualizar escenarios.

El proyecto se integraba en sus pipelines de CI/CD de Jenkins, por lo que cada commit en una pull request (PR) se sometía a este suite de pruebas de aceptación.

Con el tiempo, la suite se convirtió en un catálogo de conocimiento de negocio, preservando errores pasados, casos extremos y requisitos en forma de especificaciones ejecutables. Para un sistema que contenía años de lógica de negocio acumulada, esta confianza se transformó en uno de los activos más valiosos del equipo.

Desventajas

Las pruebas de aceptación no son una solución mágica.

No sustituyen a las pruebas unitarias, a las pruebas de integración, a la monitorización, a las pruebas de rendimiento ni a un buen diseño del sistema. También introducen costes de mantenimiento y exigen disciplina para mantener los escenarios legibles y relevantes.

En un proyecto que ya está en marcha, implementarlas puede representar una inversión significativa si existe una brecha de conocimiento y/o una deuda técnica importante.

Sin embargo, pueden mitigar una gran parte de los problemas que suelen sufrir los sistemas de alta complejidad. El beneficio principal es simple: una suite de pruebas robusta y exhaustiva otorga la confianza de que los flujos de trabajo y la lógica de negocio se comportarán de la forma esperada tras cada cambio.

Reflexiones finales

En mi experiencia profesional, he tenido que trabajar con proyectos, arquitecturas, tecnologías y entornos de entrega muy diferentes.

Este sigue siendo uno de los entornos en los que sentí el mayor nivel de confianza a la hora de desplegar cambios. No se debió a un framework o herramienta específica, sino a la seguridad en el despliegue que nos brindaba la suite de pruebas ante cualquier cambio de comportamiento.