• Las entidades vivas de JPA Develamos el misterio: ¿qué relación mantienen los objetos con la base de datos?
  • La fábula de Arturo Un valiente caballero nos enseñará las consecuencias de la deuda técnica.
  • 4 consejos para presentar como un samurai Averiguamos lo que tienen en común un samurai y un presentador efectivo.
  • Cómo alimentar nuestra creatividad Ideas para alimentar la creatividad cotidiana de los equipos de trabajo.

bombaLas pruebas de integración son una farsa - son como un virus que se auto-reproduce y amenaza con infectar a todo el código, al proyecto, y al equipo con un dolor y sufrimiento sin fin.

Esperen un minuto... ¿¿¿cómo???

Lo digo en serio. Odio a las pruebas de integración. Las odio con ganas. Por supuesto, primero debería clarificar a lo que me refiero con pruebas de integración, porque, como muchos otros términos en el software, seguramente no estemos de acuerdo en su significado.

Utilizo el término prueba de integración para referirme a cualquier prueba cuyo resultado (éxito o fallo) dependa de una correcta implementación de más de una pieza de comportamiento no trivial.

Si, yo tamibén preferiría una definición más rigurosa, pero funciona para la mayoría de los casos. El punto es simple: en general prefiero no depender de pruebas que puedan fallar por una variedad de motivos. Estas pruebas generan más problemas de los que resuelven.

Escribimos pruebas de integración porque no podemos escribir pruebas unitarias perfectas. Todos conocemos el problema: todas las pruebas unitarias pasan, pero igualmente alguien encuentra un defecto. A veces podemos explicar esto encontrando una prueba unitaria obvia que faltaba, pero a veces no podemos. En estos casos, decidimos escribir una prueba de integración para asegurarnos que todas las implementaciones productivas que usamos en este camino de ejecución defectuoso ahora funcionen correctamente.

Hasta acá no es un gran problema. El monstruo recién aparece cuando pensamos esto: 

"Si podemos encontrar defectos incluso aunque nuestras pruebas pasen el 100%, y si sólo podemos tapar estos agujeros con pruebas de integración, entonces mejor escribamos pruebas de integración por todos lados".

Mala Idea. Realmente mala.

explosión nuclear

¿Por qué es tan mala? Un poquito de aritmética nos va a ayudar a explicar la situación.

Supongamos que tenemos una aplicación web mediana, con 20 páginas, 10 de las cuales tienen formularios. Cada formulario tiene un promedio de 5 campos, y cada campo necesita un promedio de 3 pruebas para verificarlo completamente. La arquitectura tiene 10 capas, incluyendo los elementos web de presentación, las páginas web de presentación, presentación abstracta, un bridge HTTP hacia nuestro API de servicios, controladores, scripts de transacciones, repositorio de datos abstractos, implementaciones de repositorios de datos, mapeos SQL, ejecuciones SQL, y configuración de la aplicación. Un ciclo típido de request/response crea un stack trace de 30 cuadros de profundidad, alguno de los cuales los escribimos nosotros, y otros provienen de algún tipo de framework que estemos usando. ¿Cuántas pruebas necesitamos escribir para probar la aplicación de forma completa?

Al menos 10.000. Quizás un millón. Un millón.

¡¿Cuánto?! Consideremos 10 capas con 3 potenciales puntos de bifurcación en cada capa. Número de caminos de ejecución: 310 > 59.000  ¿Y qué tal con 4 bifurcaciones por capa? 410 > 1.000.000  ¿Y qué pasa con 3 bifurcaciones en 12 capas? 312 > 530.000 .

Para simplificar las cuentas, supongamos que sólo necesitamos 100.000 pruebas de integración para cubrir la aplicación. Las pruebas de integración usualmente interactúan con el sistema de archivos o conexiones de red, lo que significa que se ejecutan en promedio no más de 50 pruebas por segundo. La suite de 100.000 pruebas se ejecutaría en 2000 segundos, o 34 minutos. Esto significa que vamos a eejcutar la suite entera sólo cuando estemos listos a probarlo. Algunos equipos dejan que el sistema de integración continua haga esto, y esperan que ocurra lo mejor, perdiendo tiempo valioso cuando las pruebas fallan y se enteran una hora después.

¿Cuánto se tarda en escribir 100.000 pruebas? Si nos toma 10 minutos escribir cada prueba -esto incluye el tiempo para pensar, tiempo para mantener la base de datos de prueba, el servidor web, el servidor de aplicaciones, y así - entonces necesitamos 2778 días-humano de seis horas (o días-pareja, si usamos programación de a pares). Esto es lo mismo que 556 semanas-humano de cinco días (o semanas-pareja).

Incluso aunque haya sobreestimado por un factor de cinco, igualmente necesitariamos a dos personas tiempo completo por un año escribiendo pruebas Y un flujo constante de trabajo para mantenerlos ocupados las 6 horas del día Y no van a poder equivocarse, porque no tienen tiempo para re-escribir las pruebas.

No. Vamos a tener a estos programadores de pruebas escribiendo código productivo por la semana ocho.

Como no vamos a escribir todos estas pruebas, vamos a escribir las pruebas que podamos. Vamos a escribir las pruebas para los caminos de ejecuciones felices y algunos casos de error. No vamos a comprobar todos los campos de cada formulario. No vamos a comprobar a ver qué pasa el 29 de febrero. Vamos a escribir 50 pruebas por semana, lo que se traduce en 2500 pruebas en un año. No 100.000.

El 2.5% del número que necesitaríamos para probar la aplicación completa.

Incluso aunque escribieramos el 2.5% más importante, y sabiendo de toda la duplicación de las pruebas complementarias completas, sólo cubriríamos entre el 10% y el 80% de los caminos de ejecución, y no vamos a tener idea si estamos más cerca del 10% o del 80% hasta que el cliente empiece a usar la primera entrega.

¿Y'? ¿Ya te sentís afortunado?

Así que escribimos 2500 pruebas de integración. Quizás hasta llegamos a las 5000 pruebas. Cuando el cliente encuentra un defecto, ¿cómo lo arreglamos? Si, claro: con otro grupo de pruebas d eintegración. Mientras más pruebas de integración escribimos, más alimentamos una falsa sensación de seguridad (recordemos, con esas 10 pruebas de integración extra aumentamos la cobertura de caminos del ejecución del 5% al 5.01%). Esta falsa sensación de seguridad nos ayuda a sentirnos bien al entregar más código poco probado al cliente, quien a su vez encontrará más defectos, los cuales arreglaremos con aún más pruebas de integración. Con el paso del tiempo la cobertura de caminos de ejecución decrese porque la complejidad del código aumenta más rápido que nuestra capacidad para escribir pruebas de integración que lo cubran.

... y todavía te preguntás por qué pasás el 70% del tiempo respondiendo pedidos de soporte y mantenimiento.

Las pruebas de integración son una farsa. Son una pérdida de tiempo poco confiable y que se auto-reproduce. Es momento de que se vayan.

Basado en Integration tests are a scam, part 1.

Inspiración.

"Si tú tienes una manzana y yo tengo una manzana e intercambiamos las manzanas, entonces tanto tú como yo seguiremos teniendo una manzana cada uno. Pero si tú tienes una idea y yo tengo una idea, e intercambiamos las ideas, entonces ambos tendremos dos ideas"

Bernard Shaw