Software testingReconozco que comencé a tomarme muy en serio el ser más estricto con el desarrollo y refactorings de las pruebas desde hace relativamente pocos años. Efectivamente, me llevó su tiempo darme cuenta de la enorme rentabilidad metodológica al pasar de una aplicación de consola para depurar (...) que tener formalizadas correctamente una completa y contundente batería de pruebas. Tanto es así, que hoy día sólo veo a través de las pruebas, quiero decir, cuando desarrollo nuevo código de producción, pocas veces entro en él en modo depuración si las pruebas correspondientes indican que todo va bien.

No obstante, y sin caer en la simpleza de reconocer lo fácil que es detectar en qué otros fallan, veo a menudo (muchas más veces de las que me gustaría) que el hecho de tener implantantado una arquitectura y metodología que permite y exige el crear pruebas, éstas se desarrollan como para salir del paso, en lo que se suele en llamar el happy path y que yo llamo particularmente "pruebas felices".

¿Qué es una prueba feliz?. Cuando escribimos una nueva clase o añadimos una nueva funcionalidad a código ya existente, tenemos la tendencia natural de escribir pruebas que consciente o inconscientemente sabemos que van a dar pocos problemas. Probamos entonces el mejor caso y que resuelve bien nuestro código: la prueba feliz viene a decirnos que nuestro código hace bien aquello para lo que lo hemos desarrollado. No obstante, si nos limitamos a escribir exclusivamente pruebas felices, estamos ignorando gran parte del objetivo de tener una solución respaldada por tests. Buscamos sólo pruebas felices porque en realidad percibimos el escribir pruebas como un mal que hay que asumir en lugar de un pilar fundamental y esencial en el desarrollo de un software de calidad y profesional.

El objetivo de escribir pruebas no es sólo el de tener un mecanismo por el que poder comprobar automáticamente que algo funciona ahora y seguirá funcionando en el futuro. Escribimos tests no sólo para la situación ideal (el camino feliz) sino que debemos desarrollarlos para comprobar todas aquellas situaciones incómodas en las que una funcionalidad particular se podría ver comprometida. Se nos olvida en ocasiones que los tests persiguen detectar errores, si nos quedamos con los casos más sencillos, seguramente estaremos ocultando bugs que tarde o temprano nos explotarán en las manos.

¿Cuándo es el momento más oportuno para detectar errores y problemas?, ¿cuando estamos precisamente desarrollando una nueva funcionalidad o cuando el software está ya en producción con uno o varios clientes usándolo?. La respuesta es más que obvia.

Recientemente he desarrollado un servicio de Windows para instanciar ciertos servicios web que emulan el comportamiento de un tipo de dispositivo. Se simula uno de estos dipositivos instanciando sus servicios web correspondientes en un puerto específico. Desarrollé como es lógico ciertas pruebas para garantizar que los web services se instancian bien para el puerto 8000, ¿y ya está?. Absolutamente no, ¿qué pasaría si al desplegar ese software en una máquina en producción ese puerto está ya siendo usado?. En este caso, las pruebas tienen que garantizar que somos correctamente notificados cuando se da esa circunstancia, que un error de este tipo no provoca un crash completo del servicio de Windows, etc. Si me hubiera quedado en la prueba feliz, seguramente habría terminado antes, pero con toda seguridad en el futuro habría tenido que dedicar muchísimo más tiempo a solucionar ese tipo de errores en producción y con un cliente insatisfecho...

Esto no es más que un ejemplo pero es que a veces no nos damos cuenta de la cantidad de esfuerzo y tiempo que nos podemos ahorrar detectando errores en producción sencillamente creando una batería correcta de tests en la fase de desarrollo. Pocas cosas hay que tranquilicen más en software que saber que tu producto está tan suficientemente probado que muy difícilmente se van a encontrar problemas en el despliegue del mismo.

Una ley del software viene a ser que cuanto más y mejor pruebes un software, mayor lo vas a rentabilizar, en el sentido de dedicar menos tiempo a depurar errores, el tener menos clientes reportando problemas, etc.

Tampoco es cuestión de crear el mayor número de pruebas porque sí sino de crear éstas con la calidad suficiente y cubriendo todos los posibles casos.

Este es un asunto que, me temo, solemos subestimar y es que no es trivial crear y saber desarrollar pruebas con la suficiente calidad; el problema es que en nuestra profesión muy a menudo debemos tener un carácter polifacético (lo que viene siendo tener que hacer de todo un poco); este no es un tema sencillo sino que el tester es un claro perfil de persona cualificada con ciertas aptitudes en su profesión, como bien indica este magnífico libro de Software Testing.

A veces me he planteado la pregunta de cómo evaluar un buen software de uno que no lo es tanto. Aquí entran en juego seguramente aspectos muy subjetivos; sin embargo, si intentamos llegar a algún tipo de principio del tipo de los que muestra Max Kanat en su libro Code Simplicity, existen realmente varias maneras de evaluar la calidad de un buen software.

No me gusta nada ni siquiera plantear el concepto de calidad, ya que en la mayoría de las ocasiones, los desarrolladores de software hacen lo que pueden en el contexto laboral con el que les toca lidiar; pocas veces he visto que realmente las cosas se hagan mal por pura y llana pereza mental. Sí he visto muchas a menudo que las cosas se hacen mal por ingenuidad o por la falta de un tutor que sirva de guía y ganas de traspasar su experiencia.

¿Cómo entonces distinguir una librería o trozo de software bien hecho de otro no tan bueno?.

Un error muy común que cometen muchos desarrolladores de software es escribir código de manera que es difícil crear a su alrededor las suficientes pruebas o tests que garanticen que ahora y más adelante, el software funciona.

Esto es un mantra que repito a menudo: la estructura de una solución que puede ser probada no tiene nada que ver con la estructura de otra para la que es imposible crear un conjunto de tests. Por tanto, aquí tenemos un elemento que nos puede indicar en cierta medida la calidad de una pieza de código: si se puede probar con facilidad o dificultad.

Pero, ¿qué hay del mantenimiento?, ¿no es verdad que queremos escribir software que viva muchos años y que pueda ser vendido y desplegado en el mayor número de clientes posible?. ¿Cómo vamos a hacer esto si la solución que escribimos es imposible de mantener?. Volvemos a la metáfora del coche que no se puede reparar...

Del mismo modo que antes, un buen software escrito para facilitar su mantenimiento no tiene nada que ver en su forma y estructura de otro que es imposible o muy difícil de mantener (diseño rígido), entendiendo por mantenimiento la detección fácil de pequeños bugs y la capacidad de mejorar el producto con nuevas características o mejoras de las ya existentes.

Efectivamente, con el tiempo nos damos cuenta de que el diseño, estructura y forma de un software que permite ser probado con facilidad y que puede ser mantenido con sencillez, no tiene nada que ver con el diseño, la estructura y forma de un software que ni podemos probar bien y para el que es muy complicado introducir algún cambio.

Esto es un principio de desarrollo de software inquebrantable que uno termina por aprender a lo largo de varios años después de algunas etapas de fracasos y errores.

Cuando llegamos a este tipo de conclusiones, nos damos cuenta de que programar bien no se consigue sencillamente leyendo un buen manual de C#, Ruby on Rails o lo que sea; conocer los rudimentos de cualquier tecnología no es suficiente. Existen principios, leyes, diseños, etc. que nos indican realmente cómo llegar a una solución con la suficiente calidad.

¿Por qué leer El Libro Negro del Programador?

Adquirir desde:
Amazon (kindle eBook / papel)
CreateSpace (papel)
PayHip (epub / mobi / pdf)

El libro negro del programador.com
Segunda Edición - 2017

El libro negro del programador.com
Now available in english!

Archivo

Trabajo en...

Mis novelas...