Muchas personas saben programar, pero pocas saben “desarrollar”. Desarrollar no sólo es escribir código, es hacerlo bien y TDD, el tema de hoy, es una herramienta para lograr ese objetivo.

Manteniendo todo en orden

Al hacer un producto de software, una web API, por ejemplo, siempre hay sistemas que mantienen todo bajo control: Git y GitHub nos ayudan a mantener el código versionado y guardado, las metologías ágiles mantienen al equipo y el trabajo en un ritmo de trabajo controlado y, como estas, hay más herramientas que evitan que nuestro producto se convierta en un development hell. Pero, no hay un sistema que nos diga en qué orden hacer el código. Aquí es donde entra al espectáculo el panorama de TDD.

¿Qué es el TDD?

TDD o Test Driven Development (desarrollo basado en tests, por su traducción al español), es una pespectiva de desarrollo donde, como su nombre lo dice, predominan los tests o pruebas del sistema. Estas pruebas pueden ser unitarias, de integración, punto a punto, etcétera. La gracia del TDD es que, antes de programar y desarrollar la plataforma, tengamos instrumentos a través de los cuáles medir los avances que hagamos. Sólo hagámonos las siguinetes preguntas: ¿Cuántas veces no ha pasado que hacemos algo del software, para darnos cuenta al final que obviamos algo, y tenemos que volver a programarlo? Incluso si no te confundes y eres un desarrollador experimentado ¿Cómo te aseguras que las especificaciones para terminar una funconalidad o feature del sistema no van a ser interpretados de diferente manera por diferentes programadores? Sin duda, tener las pruebas desde un principio nos ayuda a solucionar estos problemas y mejorar la eficiencia de nuestro trabajo.

Vamos directo al grano...

Bueno, ¿cómo implementamos TDD? Veremos un pequeño ejemplo con Node JS, el framework Hapi.js y la librería de pruebas Jest. Para este ejemplo se considera que el lector posee conocimiento básicos para desarrollar un web API con Hapi.js y crear pruebas unitarias con Jest.

Primero que nada, antes de desarrollar algo, siempre tenemos que generar una historia de usuario, una épica o algún issue que defina la funcionalidad que queremos crear. Para nuestro ejemplo, estaremos desarrollando una plataforma de cursos en línea, por lo que una de sus tareas es poder registrar cursos:

Como administrador quiero registrar un curso a la plataforma:
Al hacer una petición POST a la web API en el endpoint “/courses”, con un payload que representen los datos del curso a ingresar, se debe crear en la base de datos un registro que contenga tales datos.
Ejemplo de payload:
nombreCurso: “Curso de Node js”
sesiones: 5
dificultad: “Fácil”

Genial. Ahora nos toca escribir los tests para que el desarrollador pueda comprobar si el código que escriba en un futuro estará bien.

En código anterior es una prueba unitaria que hace una petición POST a la web API para crear un curso, devolviendo un código HTTP 200, tal como queríamos. Sin embargo, hay ciertos comportamientos que no definimos explícitamente. Por ejemplo, se espera que la API devuelva el identificador de curso, aunque no estaba en la descripción de la tarea.

Este tipo de discrepancias suelen suceder, pero no por que sea un error, sino por convenciones del equipo de trabajo. Muchos desarrolladores suelen retornar el ID del registro creado después de un POST, y sería muy engorroso anotarlo como requisito en todas las descripciones de features de creación. Sin embargo, ya que tenemos el código de la prueba unitaria, fácilmente nos podemos dar cuenta de qué es lo que en realidad se necesita que realice el programador. De esta manera mantenemos limpias las descripciones de tareas que nuestro equipo tenga en GitHub, obviando todo aquello que se haya acordado generalizar, dando más enfoque a los detalles propios de la tarea y, en caso de que un desarrollador tenga dudas sobre qué exactamente se debe realizar, puede dar un vistazo a las pruebas unitarias.

Siguiendo con el ejemplo, desarrollamos la parte correspondiente a la creación de cursos en la web API y, durante este tiempo se pueden ejecutar las pruebas para saber cuándo una tarea está completada. De igual forma, TDD nos tiene varias ventajas, no sólo al crear nuevas funcionalidades, sino al trabajar sobre código ya escrito. Los tests dirán si, de manera accidental, estropeamos algo que otra persona hizo, haciendo del proceso de debugging algo más fácil y sencillo.

Conclusión

TDD hace el desarrollo más fácil y ordenado, de eso o hay duda. De hecho, TDD sólo es uno de los muchos paradigmas para desarrollar, existen otros como BDD, y te lo contaremos en el siguiente post.