¿Qué es el testing basado en modelos?

El testing basado en modelos (MBT) es un enfoque donde creas un modelo formal del comportamiento esperado del sistema, y luego usas herramientas para generar automáticamente test cases a partir de ese modelo. En lugar de escribir manualmente cientos de tests, construyes un modelo y dejas que los algoritmos deriven los tests.

El flujo de trabajo MBT:

  1. Analizar requisitos — entender el comportamiento del sistema
  2. Construir un modelo — representar el comportamiento como modelo formal
  3. Generar tests — usar herramientas MBT para derivar test cases
  4. Ejecutar tests — correr los tests generados contra el sistema
  5. Evaluar resultados — el modelo sirve como oráculo
  6. Mantener el modelo — actualizar cuando cambien los requisitos

¿Por qué MBT?

Problemas del diseño manual:

  • Diseñadores interpretan requisitos diferentemente
  • Se pierden caminos importantes
  • Mantener miles de test cases manuales es costoso
  • Criterios de cobertura son difíciles de satisfacer manualmente

Ventajas de MBT:

  • Cobertura sistemática garantizada
  • Regeneración automática al cambiar el modelo
  • Construcción del modelo revela ambigüedades en requisitos
  • Escalabilidad — modelos describen comportamiento concisamente

Tipos de modelos para MBT

Máquinas de estado finitas (FSM)

Ejemplo: Sesión de ATM

Estados: Idle, CardInserted, PINEntry, Authenticated, Transaction, Dispensing, Error
Transiciones:
  Idle → CardInserted [insertCard]
  CardInserted → PINEntry [cardValid]
  PINEntry → Authenticated [correctPIN]
  PINEntry → PINEntry [wrongPIN, attempts < 3]
  PINEntry → Error [wrongPIN, attempts >= 3]
  Authenticated → Transaction [selectWithdraw]
  Transaction → Dispensing [sufficientFunds]
  Dispensing → Idle [cashTaken]
  Error → Idle [ejectCard]

Máquinas de estado extendidas (EFSM)

FSMs con variables, guardas y acciones.

Diagramas de actividad UML

Para workflows y procesos de negocio.

Cadenas de Markov

Modelos probabilísticos para testing estadístico.

Criterios de cobertura

CriterioDescripciónRigor
Cobertura de estadosVisitar cada estadoDébil
Cobertura de transicionesTomar cada transiciónModerado
Cobertura switchCada par de transiciones consecutivasFuerte
All-pathsCada camino distintoMás fuerte

Herramientas MBT

Open Source

  • GraphWalker — Java, FSM y EFSM, API REST
  • ModelJUnit — Extensión JUnit para FSM
  • NModel — Framework .NET
  • Spec Explorer — Microsoft, testing de protocolos

Comerciales

  • Conformiq — Enterprise MBT
  • Smartesting — Generación con UML
  • MaTeLo — MBT con cadenas de Markov

Cuándo MBT funciona mejor

Buenos candidatos:

  • Implementaciones de protocolos (APIs, protocolos de red)
  • Sistemas embedded con comportamiento de estado definido
  • Workflows de procesos de negocio
  • Sistemas con muchos caminos válidos
  • Productos de larga vida

Malos candidatos:

  • Aplicaciones CRUD simples
  • Aplicaciones heavy en UI
  • Sistemas donde los requisitos cambian más rápido que los modelos
  • Proyectos únicos

Ejercicio: Construyendo un modelo MBT

Problema 1

Construye un modelo de máquina de estados para un carrito de compras:

  • Cart empieza Empty
  • Se pueden agregar items (Empty → HasItems, HasItems → HasItems)
  • Se pueden remover items (HasItems → HasItems o HasItems → Empty)
  • Proceder a Checkout (HasItems → Checkout)
  • Aplicar cupón (Checkout → Checkout)
  • Enviar orden (Checkout → OrderPlaced)
  • Orden falla (Checkout → PaymentFailed)
  • Reintentar (PaymentFailed → Checkout)
  • Volver al carrito (Checkout → HasItems)
Solución

Estados: Empty, HasItems, Checkout, PaymentFailed, OrderPlaced

Transiciones:

  1. Empty → HasItems [addItem]
  2. HasItems → HasItems [addItem]
  3. HasItems → HasItems [removeItem, items > 1]
  4. HasItems → Empty [removeItem, items == 1]
  5. HasItems → Checkout [proceedToCheckout]
  6. Checkout → Checkout [applyCoupon]
  7. Checkout → OrderPlaced [submitOrder, success]
  8. Checkout → PaymentFailed [submitOrder, fail]
  9. PaymentFailed → Checkout [retryPayment]
  10. Checkout → HasItems [backToCart]

Tests para cobertura de transiciones:

Test 1 (cubre 1, 2, 5, 6, 7): addItem → addItem → proceedToCheckout → applyCoupon → submitOrder(success)

Test 2 (cubre 3, 4): addItem → addItem → removeItem → removeItem

Test 3 (cubre 8, 9, 10): addItem → proceedToCheckout → submitOrder(fail) → retryPayment → backToCart

3 tests cubren las 10 transiciones.

Problema 2

Evalúa si MBT es apropiado para estos proyectos:

  1. API bancaria con 50 endpoints y gestión de estado compleja
  2. Landing page de marketing con formulario de contacto
  3. Firmware IoT que gestiona sensores, alertas y protocolos
Solución
  1. API bancaria — Sí. Estado complejo, protocolo definido, muchos caminos, requisitos regulatorios.
  2. Landing page — No. Comportamiento simple, el esfuerzo de modelado excede el beneficio.
  3. Firmware IoT — Sí. Estados definidos, comportamiento predecible, testing de conformidad de protocolo.

Desafíos y limitaciones

  • Mantenimiento del modelo: Debe sincronizarse con el sistema
  • Complejidad del modelo: Si es tan complejo como el sistema, se pierde el beneficio
  • Curva de aprendizaje: Equipos necesitan capacitación
  • Problema del oráculo: ¿Qué pasa si el modelo está mal?
  • Propiedades no funcionales: MBT no aborda performance ni seguridad directamente

Puntos clave

  • MBT genera tests automáticamente desde modelos comportamentales
  • Las FSM son el tipo de modelo más común
  • Las herramientas garantizan criterios de cobertura (estados, transiciones, switch)
  • Construir el modelo revela ambigüedades en requisitos
  • Mejores candidatos: protocolos, sistemas embedded, workflows complejos
  • El modelo sirve como generador de tests y como oráculo
  • El mantenimiento del modelo es el mayor costo continuo