Uno de los desafíos más grandes de la Ingeniería de Software es lograr garantizar la calidad de los productos de software y mejorar la productividad a lo largo del ciclo de vida del mismo, desde el comienzo del desarrollo hasta las etapas de mantenimiento. Básicamente que la vaina de programa no me complique la vida.

A lo largo del tiempo de vida del proyecto surgen cambios en los requerimientos del software con lo cual muchas veces debemos modificar una funcionalidad ya establecida del sistema y es con estos cambios donde se pueden introducir nuevos errores. Estos errores a veces pueden ser fácilmente detectados con una sencilla prueba manual del sistema, es decir, metes datos como loco al programa y esperas a ver que sale; a medida que el proyecto crece en tamaño se torna algo imposible de lograr en un tiempo razonable, ya que estas pruebas «manuales» toman mucho más tiempo y por lo general son repetitivas, puede que en una de esas repeticiones no hayamos prestado la suficiente atención y toma! un rico bug al cliente.
Este bug a veces puede significar pérdida de dinero de nuestros clientes o incluso peor, puede significar la vida de una persona, y es aquí en donde la importancia de tener un «repelente de bugs» se torna más que necesario. nota: bug = error del sistema

Si bien el testing no asegura que no existan fallas, sí permite evaluar la confiabilidad del producto a construir y dar una noción de la calidad del producto que se está construyendo. El testing permite detectar cuándo y cómo el software falla.[1]

Existen diferentes tipos de Tests:

Test de aceptación: es un test que permite comprobar que se está cumpliendo con un requerimiento del negocio. Son pruebas escritas en lenguaje del cliente pero que puede ser ejecutado con la máquina. Esto nos permite probar que el software que estamos desarrollando cumple con las expectativas del cliente y de los usuarios.

Test funcionales: esta expresión es utilizada para determinar a aquellas pruebas que agrupan a varios tests de aceptación y prueban alguna funcionalidad del negocio propiamente dicha.

Test de sistema: integra varias partes del sistema, incluso puede probar toda la aplicación o varias funcionalidades juntas. Estos tests se comportan de manera similar y buscan emular el comportamiento de los usuarios del sistema.

Test unitarios: son los tests ineludibles, son los necesarios y los más importantes para los desarrolladores, todo test unitario debe ser rápido, atómico, inocuo e independiente, sino cumple con estas cuatro premisas no es un test unitario. Un test tiene que ser rápido porque se ejecutan muchos de ellos todo el tiempo, tiene que ser inocuo, ya que no debe alterar el estado del sistema, para ser atómico debe probar la menor cantidad posible de código y por último para ser independiente no debe depender de que otros tests unitarios sean exitosos o fallen para ser él mismo exitoso. Un test unitario se aplica a una parte específica del código.[2]
Una forma chévere de ver una analogía a los test unitarios es como la expone @benzado [3] a continuación lo transcribo:

El testing Unitario es como ir al gimnasio. Tú sabes que es bueno para ti, todos los argumentos tienen sentido, entonces empiezas a ejercitarte. Hay un ímpetu al principio, lo cual está bien, pero luego de varios días empiezas a preguntarte si vale la pena tomarse la molestia. Estás tomando una hora de tu día para cambiarte de ropa, y ponerte a correr en una bola para hamsters y no estás seguro si estás ganando algo más que solo dolor de brazos y piernas.

Luego, después de una o dos semanas, tan pronto los dolores van desapareciendo, un gran Deadline se acerca. Tal vez te encuentres tan ocupado que necesitas invertir tu tiempo sólo en lo que sea trabajo útil, entonces dejas de ir al gym. Empiezas a quitarte el hábito y cuando el Deadline termina tratas de volver a lo que estabas haciendo antes de eso, ir al gimnasio. Si logras arreglártelas para convencerte en ir de nuevo, vas a sentir el mismo dolor que cuando fuiste la primera vez.

Haces algo de investigación, para ver si hay algo que estás haciendo mal. Empiezas a sentir un poco de rechazo a esas personas fit que siempre hablan de las virtudes de hacer ejercicios y a darte cuenta que no tienes nada en común con ellas. Ellos no tienen que discutir con nadie acerca de los beneficios de los ejercicios; es algo que todos aceptan como importante. Cuando un Deadline se acerca, no tienen a un jefe que les dice que el ejercicio es innecesario y que sólo deben dejar de tragar.


Los test unitarios usualmente valen la pena el esfuerzo, pero la cantidad de esfuerzo que se tiene que hacer no es la misma para todos. Depende de que parte del desarrollo te encuentres al momento de empezar a hacer las pruebas. Si lo haces sobre una base de código espaguetti gigantesca y sin nada de testing, vas a estar bastante ocupado jodido y te va a tocar esforzarte mucho; en cambio si empiezas a testear desde el principio todo será infinitamente más fácil, es por esto que nació el TDD (Test-Driven-Development) cuya implementación en un proyecto está demostrado que reduce del 40-80% la densidad de producción de bugs. [4]

Como bien nos indica Jurado [2] los test unitarios son los más importantes y no deben eludirse, deben estar si o si, ya que son la base de otros tipos de test más generales.

Hay varios beneficios de realizar los tests unitarios:

Menor cantidad de Bugs:
Esto puede sonar un poco obvio. Sin test, pruebas todo de manera manual, con un código sencillito esto no es gran problema, pero cuando aumenta la complejidad se vuelve un problema. Y mientras más código tengas, más tiempo te tomará hacerlo. Además que hacerlo manualmente implica que debemos prestar mucha atención a los resultados en cada vez que probemos manualmente.. que pueden ser muchas, muchas veces durante una cantidad de tiempo razonable. Pero si ponemos nuestro mejor esfuerzo y dedicamos tiempo a realizar nuestro test notaremos la ganancia de tiempo que obtendremos al final, y lo mejor es que los test siguen sirviendo a lo largo del desarrollo del proyecto, escribes el test una vez y te aseguras de jamás volver a probar esa parte del código.

Tendrás un repelente de Bugs:
Necesitas una explicación para este beneficio? Si es así aquí tienes:
Si accidentalmente  haces un cambio que introduce un bug (suele suceder más de lo que imaginas) en el código que ya tiene un test unitario, el test detectará el bug. Es decir, no dejará que haga daño a ningún cliente en producción. 😉

Podrás desarrollar de forma segura:
Quién no ha escrito código y ha pensado alguna vez ¿Habré cagado dañado algo en otra parte? En un montón de proyectos sucede que si no se tiene tests unitarios, un cambio que haces en un lado, puede afectar en otra funcionalidad que ni tocaste, así que solo pruebas manualmente la funcionalidad que hiciste y si funciona correctamente todo el mundo es arcoiris para ti, pero lo que no sabes es que hiciste la grande en otro lado y ni por enterado.

Cuando ya se tiene una «red» de tests unitarios éstos si son detectados, y me sentiré seguro codificando porque si hago un cambio que afecte cague otra funcionalidad el test de ese otro lado saltará y te dirá que ha ocurrido mal.

Esto te suena conocido? pues si, es como hacer debugging, pero automático porque te dice:

  1. qué función falló.
  2. que se suponía que debía de hacer esa función.
  3. que hizo la función en vez de lo esperado. esto es útil cuando el debugger del lenguaje es una caca, como el de javascript

El dichoso test sirve como documentación del código:
Las razones ya fueron implícitamente dadas en los otros beneficios 😉

 

 

 

 

Referencias:

[1]D. Vallespir, 2016. [Online]. Available: https://www.fing.edu.uy/~dvallesp/wiki/uploads/Research/gacpuo.pdf. [Accessed: 11- Jul- 2016].

[2]Carlos Ble Jurado, “Diseño Ágil con TDD”, eBook. Primera Edición. Enero 2010. páginas 70-71.

[3]Is. 2016. «Is Unit Testing Worth The Effort?». Stackoverflow.Com. Accessed July 11 2016. http://stackoverflow.com/questions/67299/is-unit-testing-worth-the-effort.

[4]»TDD – The Art Of Fearless Programming | SEED: Software Engineering Evidence Database». 2016. Evidencebasedse.Com. Accessed July 11 2016. http://evidencebasedse.com/?q=node/78.