miércoles, 4 de marzo de 2009

Reflexiones sobre pruebas unitarias

Me he encontrado en proyectos donde es difícil convencer a la gente que desarrolla que hacer pruebas unitarias es bueno. Y no es porque sean personas necias, si no de cierta forma al no tener experiencia ni el habito de hacer pruebas unitarias es difícil ver el beneficio que estas nos pueden aportar (a mi me paso las primeras veces que empecé a adoptar el habito de realizar pruebas unitarias).

Es verdad que muchas veces hacer las pruebas unitarias parece una inversión de tiempo considerable que muchas veces no parece valer la pena sobre todo en proyectos con mucha presión y tiempos cortos para entregar los requerimientos a los clientes.

Saber que probar, para no hacer pruebas unitarias muy básicas o que realmente no aportan nada y solo son un desperdicio de tiempo, es cuestión de experiencia. Y esta experiencia solo se puede obtener escribiendo pruebas unitarias, ya que conforme nos vayamos dando cuenta de que vale la pena probar y que no, sabremos distinguir donde es importante invertir tiempo para hacer pruebas unitarias que nos aporten valor al proyecto.

Según mi experiencia, hacer pruebas unitarias trae consigo muchos beneficios como son:
  1. Ayudan a un mejor entendimiento del requerimiento y de esta forma se puede llegar a hacer un mejor diseño de la solución simplemente por el hecho de que al empezar a hacer primero las pruebas unitarias nos enfocamos mas en "que" tiene que hacer nuestro código en lugar del "como" tiene que hacerlo. Así pues, al forzarnos a pensar primero en el "que" en lugar del "como" terminamos teniendo un código mejor diseñado y mas fácil de usar (y probar!).
  2. El código de las pruebas unitarias sirve como "documentación" para otros desarrolladores que quieren entender el código del requerimiento.
  3. Nos sirven como herramienta. Ya que es mejor correr la prueba unitaria dándole las entradas correctas para tener la salida que esperamos que desplegar todo el sistema, levantarlo, configurarlo y seguir el flujo adecuado para tener la salida que necesitamos.
  4. Nos da confianza al ir escribiendo el código para implementar la solución a un requerimiento, ya que conforme avanzamos en el código y lo vamos probando nos vamos dando cuenta que vamos por el camino correcto.
  5. Nos da seguridad (hasta cierto punto y de acuerdo a la cantidad y calidad de las pruebas) de que el proyecto avanza y avanza bien. Al tener integración continua en el proyecto y día a día correr todas las pruebas unitarias nos va dando la seguridad de que las nuevas cosas que vamos desarrollando no afectan a lo ya desarrollado.
  6. Ayuda a que el equipo de desarrollo se sienta en plena confianza de aplicar técnicas de refactoring cada que se pueda, ya que al tener de respaldo las pruebas unitarias es mas fácil comprobar que después del aplicar el refactoring el código sigue haciendo lo que se supone debe hacer después de ver que todas las pruebas unitarias del proyecto siguen corriendo con éxito (les recomiendo el libro "Refactoring - Improving the desing of existing code") .
  7. Nos pueden apoyar a mejorar el diseño de nuestro código aplicando refactoring que nos lleve a implementar buenas practicas con patrones de diseño (echen un ojo al libro "Refactoring to Patterns").
  8. Nos dan experiencia y nos ayuda a crecer como desarrolladores. De esta forma conforme adquirimos experiencia nos ayuda a decidir de mejor forma que probar y que no. Ya que muchas veces no vale la pena probar cosas que son "demasiado sencillas como para que fallen" (como lo menciona J. B. Rainsberger en los primeros capítulos de su libro "JUnitRecipes - Practial Method for Programming Testing ").
  9. Nos ayudan a tener mensajes logs que nos dicen mas con menos palabras. Al no tener el habito de escribir pruebas unitarias y hacer debugging paso a paso caemos en el vicio de no escribir mensajes logs, al contrario de que si hacemos pruebas unitarias nos vamos dando cuenta poco a poco de que mensajes logs son mejores para comunicarnos con pocas palabras el flujo del programa y el error que pudo haber ocurrido. Esto es muy útil para diagnosticar problemas que ocurran con el sistema sobre todo cuando esta en producción.
En fin, igual y hay otros beneficios que por ahora no se me vienen a la mente.

Es indiscutible que escribir pruebas unitarias es una inversión de tiempo, pero es una inversión de tiempo que nos trae beneficios a mediano y largo plazo y sobre todo en proyectos grandes con equipos de desarrollo numerosos.

No soy el único que piensa así. Investiguen en Internet y verán muchos artículos que hablan sobre esto.

Den le la oportunidad al habito de escribir pruebas unitarias, es una inversión que les ayudara a tener menos dolores de cabeza o menos noches de desvelo al estar buscando errores en sus programas.

Lean los siguientes artículos y blogs:

http://jamesgolick.com/2007/8/28/we-dont-write-tests-there-just-isnt-time-for-luxuries
http://blog.marcchung.com/2009/02/16/why-we-test-software.html
http://searchsoftwarequality.techtarget.com/sDefinition/0,,sid92_gci1243425,00.html
http://www.readwriteweb.com/archives/12_unit_testing_tips_for_software_engineers.php
http://www.javaworld.com/javaworld/jw-08-2008/jw-08-unit-testing-doomed.html?page=1
http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks

¿Que opinan de esto?

No hay comentarios: