Pruebas unitarias de desarrollo Desarrollo

Por qué hacer pruebas unitarias: las 4 fases mentales de todo desarrollador

10/07/20 7 min. de lectura

Actualmente trabajo como Software Engineer en el Grupo (👉por cierto están buscando a personas para trabajar en esta posición 👈) y he tenido que realizar muchos desarrollos en todo lo que llevo de carrera, por lo que sé como piensa y como se siente una persona cuando los termina.

Una vez acabado un desarrollo, todo desarrollador ha tenido las siguientes sensaciones…

  • ¡Qué pereza! Ahora que he terminado de desarrollar, tengo que probar el desarrollo y tengo muchas cosas más importantes que hacer…
  • Si lo he hecho con cuidado ¡Seguro que está bien!.

Pues bien, la experiencia nos dice que nadie es tan bueno como para no cometer fallos y que no hay nada más importante que probar lo que se ha implementado.

A través de este post, te voy a enseñar algunas técnicas para implementarlas, comentaré algunas librerías de Java (y otras) e intentaré mostrarte los beneficios que pueden llegar a tener; y además lo voy a hacer pasando por las fases mentales que todos los desarrolladores pasamos. Asique ¡adiós pereza y hola pruebas unitarias!

¿Qué son las pruebas unitarias? 🧐

Lo primero de todo es definir que debemos considerar una prueba unitaria, si miramos en la Wikipedia encontramos… “una prueba unitaria es una forma de comprobar el correcto funcionamiento de una unidad de código

Una definición un poco más “de andar por casa” es la elaboración de un código que nos permita comprobar que si en una línea tenemos que sumar dos números, que esa suma sea correcta.

Fase Mental 1: Curiosidad ¿Cómo puedo desarrollar pruebas unitarias? El Test Driven Development 💻

Las pruebas unitarias aseguran el correcto funcionamiento de los componentes de SW. Para realizarlas podemos usar técnicas, como por ejemplo el TDD (Test Driven Development).

El TDD es una técnica de desarrollo por el cual se implementa primero el caso de test y a continuación se implementa el caso de uso.

Imaginemos que tenemos un caso de uso que nos dice si un número es par o impar, el proceso sería el siguiente: primero implementaremos los casos de pruebas, para ello tenemos que pensar las posibles respuestas que podemos tener, en este ejemplo, solo tendríamos dos, o el número recibido es par o es impar. Por lo que se tendrán que implementar 2 casos de test.

  • Test 1: esPar(4) = true
  • Test 2: esPar(7) = false

Los teóricos del TDD indican que una vez generados los test, hay que ejecutarlos antes de implementar el caso de uso (para ver qué falla realmente),  a continuación implementar el método y seguidamente volver a ejecutar el test (para ver que funciona correctamente) a este proceso se le conoce como Red/Green.

Una vez que sé que el método funciona, debemos plantearnos una posible refactorización del código implementado (si fuera posible) para mejorar el rendimiento.

Puede parecer un poco tedioso para un desarrollador, cualquiera en su sano juicio puede preguntarse… ¿para qué voy ejecutar algo que aún no tengo implementado? Por suerte, a la hora de la verdad cada desarrollador utiliza su propia técnica y estas son muy diversas, desde implementar el caso de uso y luego el Test, o incluso implementar todo el aplicativo y luego probar, lo más importante… no olvidarnos del objetivo, elaborar el test y cubrir todas las respuestas.

Fase Mental 2: Interés ¿Qué existe en la tecnología relativo a las pruebas unitarias? ⚙️

Con la evolución de los lenguajes de programación y sus librerías se ha facilitado bastante la implementación de este tipo de pruebas.

El ejemplo de Java 🔥

En Java existen multitud de librerías que podemos utilizar para elaborar los test unitarios:

  • Mockito, Powermock, estas librerías nos dan la posibilidad de simular llamadas a servicios externos (como servicios REST, servicios SOAP,…)
  • H2, esta dependencia nos permite generar una BBDD en memoria para poder realizar pruebas “reales” sobre una BBDD simulada.
  • Podam (POjo DAta Mocker), nos permite inicializar clases Java con valores aleatorios y así no tener necesidad de generar el objeto de la manera tradicional

Todas estas librerías (y muchas más que podríamos mencionar) nos permiten cubrir de manera simulada prácticamente toda la funcionalidad implementada sin necesidad de realizar llamadas a entornos reales.

Otras herramientas útiles en las que debemos apoyarnos serían:

  • Herramientas de integración continua (Jenkins, Bamboo, Concourse CI, …) con estas podemos asegurar, a través de estas pruebas el correcto funcionamiento del SW en los distintos entornos en el proceso de integración continua, éstas herramientas nos ofrecen la posibilidad de ejecutar las pruebas en los distintos procesos (despliegue a certificación, pre-producción,…) garantizando que el SW que se está moviendo sigue funcionando correctamente
  • Herramientas de análisis de código (Sonar) que junto con uso de librerías como jacoco nos permiten analizar la cobertura de código y generar informes de la misma, e incluso bloquear despliegues que no cumplan unos requisitos mínimos.

Os acabo de presentar uno de los mayores temores de los desarrolladores, ¡no pasar la cobertura!

Fase Mental 3: Duda.¿es realmente útil? 🧠

A medida que un desarrollador va desarrollando aplicaciones, va descubriendo que las pruebas son realmente necesarias y que aportan mucho más de lo que en un principio parece, desde detectar fallos en el planteamiento del código, hasta detectar fallos de codificación involuntarios que se hayan podido producir. Con el paso del tiempo vamos asumiendo la recomendación antes que la obligación… e incluso desaparece el miedo a jacoco!

Aun si con todo esto no te he convencido, mira este  par de usos más:

  • Aunque ya lo he comentado, un uso importante es asegurar que el código sigue funcionando en los distintos despliegues, es una forma que tenemos de asegurarnos que lo que estamos desplegando va a funcionar como esperamos que funcione.
  • Uno de los usos que menos se valoran es la prueba de regresión de un SW, ya sea por un evolutivo o por una incidencia. Ante una modificación de SW, las pruebas unitarias nos garantizarán que lo que hemos tocado no rompe ninguna funcionalidad implementada anteriormente y en caso de romperla podemos actuar de manera prematura al envío del SW.

¿A quién no le ha pasado de arreglar una cosa y romper otra? Con un buen test set de pruebas, estos problemas se reducen de manera drástica.

Fase Mental 4: Aceptación ¡Cambiemos la mentalidad! 🤯

En definitiva lo fundamental es cambiar el chip de los desarrolladores, muchos a día de hoy siguen viendo las pruebas unitarias como una obligación, es típico escuchar la frase:

¡Bah! ahora tengo que picarme los test

Pero, ¿sabes de todo lo que te puede salvar esta simple prueba?

Tenemos que luchar por ese cambio y que las pruebas unitarias se vean como una potente herramienta que nos ayuda durante todo el desarrollo, y elaborar un test set muy completo que asegure que nuestro desarrollo va a funcionar y que toda línea implementada hace lo que esperamos que haga.

Y ahora qué respondes, ¿obligación o recomendación? 🤨

Nacho-martin

Nacho Martín

Santander Global Tech

Ingeniero informático con vocación tecnológica, entusiasta de la programación, puedo programar desde la lavadora hasta una aplicación en la nube! Soy bastante inquieto y tiendo a automatizar las tareas tediosas que a nadie le gustan… En mis ratos libres disfruto de la familia y amigos.

 

Otros posts