Pruebas unitarias: imprescindibles para programar

Las pruebas unitarias han cogido cada vez mayor importancia gracias, por ejemplo, a la concienciación para entregar productos de calidad. ¿Tienes claro qué son?¿Sabes por qué y cuándo deberías realizarlas?

¿Qué son las pruebas unitarias?

Las pruebas unitarias (también test unitarios, o unit testing) son un método de pruebas de software que se realizan escribiendo fragmentos de código que testeará unidades de código fuente. El objetivo es asegurar que cada unidad funciona como debería de forma independiente.

No existe una definición cerrada respecto a lo que es una unidad de código, podría ser una clase, o podría ser simplemente un método.

Las pruebas unitarias son las primeras que se realizan ya con código escrito, y las crea el propio desarrollador.

Es importante también tener claro, que las pruebas unitarias, como el resto de pruebas, no demuestran la ausencia de errores en el código, ya que éstos pueden ser errores de integración, rendimiento, etc… que los test unitarios no son capaces de detectar.

Estructura de las pruebas unitarias

Por norma general, los unit test deberían seguir una estructura AAA, sobretodo para facilitar su lectura y entendimiento. AAA son las siglas de:

  • Arrange (Organizar): En esta parte de la prueba, debes establecer las condiciones iniciales para poder realizarla, así como el resultado que esperas obtener. Y esto significa por ejemplo, declarar las variables y crear las instancias de los objetos.
  • Act (Accionar): Es la parte de ejecución, tanto del fragmento de código de la prueba, como del fragmento de código a testear.
  • Assert (Comprobar): Por último, se realiza la comprobación para verificar que el resultado obtenido, coincide con el esperado.

Principios de una prueba unitaria

Las pruebas unitarias cumplen una serie de características, que te serán más fácil de recordar por FIRST.

¿Recuerdas que las pruebas unitarias son las primeras que debes realizar como desarrollador? Pues, no te olvides entonces el acrónimo FIRST, que está compuesto por:

Fast (Rápida)

Los test unitarios deben completar su ejecución lo más rápido posible. Al ser pruebas que se realizan (o deberían realizarse) sobre fragmentos pequeños de código, deben finalizar su ejecución lo antes posible.

Isolated/Independent (Aislada/Independiente)

En las pruebas unitarias, el objeto de prueba no debe depender de otra unidad de código (Recuerda la modularidad como característica de la programación orientada a objetos)

Esto no significa que no requiera de datos para poder ejecutar ese código, pero esto se realizará a través de mocks o stubs, que vienen a ser «objetos falsos» creados específicamente para realizar las pruebas.

Pero, en ningún caso, utilizaremos otras partes del código que no forme parte del unit test.

Repeatable (Repetible)

Las pruebas unitarias deben poder repetirse. De hecho, lo vas a repetir muchas veces

Por ejemplo, ten en cuenta que deberías ejecutar las pruebas cada vez que quieras subir nuevo código al repositorio.

Self-Validating (Autovalidable)

Los unit test deben mostrar de forma clara, y sin que sea necesario tu intervención, el resultado de la prueba.

Gracias a la parte de «arrange», donde estableces los resultados a obtener, la parte de «assert» puede responder si la prueba ha sido satisfactoria o no.

Timely (En el momento oportuno)

Los test unitarios deben realizarse lo antes posible, el código no debe llegar a producción sin haber escrito y superado las pruebas unitarias.

Incluso, si es posible, deberían desarrollarse antes que el código (Test Driven Development)

Test Unitarios

¿Por qué deberías hacer pruebas unitarias?

¿Imaginas un cocinero que no pruebe la comida que hace?¿Un piloto que no revise que todos los elementos del avión funcionan correctamente? Pues teniendo en cuenta la cada mayor importancia que tiene el software hoy en día, debería ser inconcebible un programador que no realice pruebas unitarias.

Y por si aún tienes dudas sobre si te conviene o no hacerlas. O si piensas que no tendrás tiempo para prepararlas, te cuento varias ventajas:

  • Menos errores en producción: Ya que previamente a subir el código has evaluado que todo funciona correctamente de forma individual y son la antesala de las pruebas de integración
  • Resolución de errores más rápida: Gracias a una detección temprana de los bugs, es más fácil y rápido solucionarlo que cuando existe más código y componentes integrados.
  • Comprensión del código: Los test ayudan a comprender mejor cómo deben funcionar las clases, y los resultados que deben mostrar cuando se ejecuta un método. Esto también ayuda en gran medida a que el código sea más fácilmente mantenible.
  • Sencillez de integración: Si todos los test unitarios se han superado, no es seguro que los test de integración se superen, pero al menos sabes que no son problemas individuales de algún componente.
  • Facilitan mejorar la estructura: Es difícil mejorar algo si verificar que funciona correctamente te lleva mucho tiempo. La sencillez y velocidad de este tipo de pruebas, fomentan que los desarrolladores puedan mejorar el código gracias a que es más fácil validar que el nuevo código funciona.
  • Localización de errores: Te será más fácil encontrar donde está el error, ya que cada prueba que falle, al realizarse sobre una unidad de código, indica claramente el componente que falla.
  • Reducción de costes: La recopilación de todas las ventajas anteriores, conlleva inevitablemente un incremento de la productividad , y con el ello, una reducción de costes.

Cuándo hacer pruebas unitarias y cuándo no

Aún con la importancia que tienen las pruebas unitarias, y las ventajas que te acabo de contar, no se deberían realizar en todos los casos, ya que podría ser contraproducente.

Te doy algunos ejemplos:

  • La naturaleza del código que estás desarrollando hace que éste cambie mucho en muy poco tiempo.
  • El periodo de vida del producto es (extremadamente) muy reducido
  • Los componentes con menor relevancia dentro del código en caso de contar con tiempos de entrega muy reducido.

Como ves, las excepciones son muy pocas, y se resumen en los casos de código que existirá durante muy poco tiempo o a penas se use, ya que en un sector donde el tiempo apremia tanto, no es necesario comprobar el 100% del código e invertir más en pruebas que en desarrollo o uso del producto.

Frameworks para pruebas unitarias

Bueno pues, si ya te he convencido (y espero que si) de que tienes que hacer pruebas unitarias para programar mejor, estos son los frameworks a los que deberías echar un vistazo para empezar a ponerlo en práctica. Algunos de ellos, son instancias de la arquitectura xUnit, que es el colectivo de nombres utilizado por varios frameworks de pruebas unitarias, y que derivan de SUnit (Desarrollado por Kent Beck, uno de los firmantes del manifiesto ágil)

Java

Para Java cuentas con JUnit, en el momento de escribir el artículo va por su versión 5 y tienen una buena guía de usuario.

Inspirado en JUnit, tienes TestNG. La ventaja de TestNG es que es más configurable que JUnit, y permite una mejor parametrización de las pruebas que quieres ejecutar.

PHP

Para PHP dispones de PHPUnit, está desarrollado por Sebastian Bergmann y es Open source.

Para instalarlo, puedes hacerlo descargando un .phar, o a través de Composer.

También cuenta con una buena documentación.

Javascript

Para Javascript, existe una mayor variedad de frameworks, entre los que podría destacar MochaJS o JEST.

En el caso de MochaJS, trabaja tan bien con el front end como con el back end.

Mientras que JEST, destaca por su sencillez.

C#

NUnit es el framework Open source de pruebas unitarias para .NET más conocido. Las pruebas pueden realizarse tanto desde la consola, como con Visual Studio, o a través de terceros.


Así que ya sabes, si quieres que tu software no tenga errores, empieza por los test unitarios, y si no lo haces porque te lo digo yo, haz caso a este hombre tan simpaticote 🙂

PruebasUnitarias

¿Ves alguna ventaja o inconveniente más en las pruebas unitarias? Me lo puedes decir en los comentarios.

Deja un comentario