El 1 de marzo de 2025 impartí un taller introductorio a Test-driven Development en la JSConfES, en Madrid. Un evento magnífico organizado por Midudev y KeepCoding. El material del taller lo preparamos los días previos entre varias personas de Lean Mind. Sabíamos que el taller solamente duraría una hora y cuarto , aproximádamente, lo cual suponía un reto para plantear una sesión en la que todo el mundo tuviese tiempo de ponerse manos a la obra, a leer y escribir código. Solamente explicando teóricamente lo que es TDD y haciendo una pequeña demo en el proyector ya podríamos habernos tomado toda la hora. Así que adelantamos una parte del trabajo y llevamos ya unos test planteados.
En la preparación del taller, resolvimos el juego del ahorcado con TDD. Luego eliminamos la implementación y dejamos solo los test. En base a estos test, las personas que quieran practicar con el ejercicio se centran en hacer pasar esos test, uno a uno. Son test que están ignorados, que no se están ejecutando (porque llevan .skip
). Hay que ir descomentándolos uno a uno para que se ejecuten. Empezando por el primero que aparece en el fichero de test. Se habilita, se ejecuta, se ve fallar y se escribe el código mínimo para que el test pase. Nada más. Hay que esforzarse por “hackear” la implementación para escribir la más rápida, la más sencilla. Aún sabiendo que no es una implementación válida para cubrir todos los casos. Esto es más difícil de hacer de lo que parece. Tenemos la tendencia a escribir todo el código de la solución de golpe. Tomarse un momento para escribir un pequeño apaño que haga el test pasar, supone un esfuerzo al principio. Hay que tener en cuenta que tiene que pasar este último test y también todos los que ya estuvieran pasando antes. Esto nos va a obligar a escribir un código de solución que cada vez es algo más genérico, para recoger los casos que se van añadiendo, es decir, los test que se van habilitando.
Así, en escasa hora y media o dos horas, una persona que nunca halla hecho TDD tiene la experiencia de seguir un flujo típico de TDD, partiendo de trabajo bien hecho. En este repositorio están bien puestos los nombres de los test. El nombre de un test refleja una regla de negocio, un comportamiento del sistema. Por ejemplo:
Desgraciadamente, en el “mundo real”, es poco habitual que los test sean reglas de negocio. Lo que más habitualmente nos encontramos en proyectos es que la gente describe datos de entrada o de salida del test. Por ejemplo, para el test de antes, lo típico (y desaconsejado) serían nombres como estos:
Un buen nombre de test debería de servir como especificación técnica del comportamiento del sistema. Es decir, si copia y pego los nombres de los test en un documento y solamente le entrego eso a una persona que desarrolla, esta debería de ser capaz de entender qué funcionalidad tiene que implementar. Con los ejemplos anteriores es imposible saber qué debo implementar. Con los nombres que hemos usado en el repositorio, sí. Escribir nombres de test cuesta mucho. Este esfuerzo de pensar (un poco) antes de programar, nos ahorra muchísimo tiempo, dinero y molestias.
Otra cosa que está bien planteada en el ejercicio es que se ha diseñado una API muy clara, concreta, específica, con tipos propios que son expresivos. Es un diseño muy evidente. Esta es otra de las virtudes de TDD, que nos invita a pensar sobre el diseño que queremos y empezar a consumirlo antes de implementarlo. Así podemos pensar en qué artefactos necesitaremos, en qué dependencias hay entre ellos, en qué tipos o clases son más adecuados, en cómo queremos gestionar los errores, etc etc. Se puede pensar todo esto sin haber implementado nada, de manera que luego la implementación va guiada por el objetivo, que es una API clara, expresiva, sin sorpresas.
En TDD, primero hacemos una lista de casos que resolver (TODO list). La priorizamos. Definimos las reglas de negocio y las asociamos a los casos o test (example mapping). Usamos esos nombres de test, las reglas. En este taller ya empezamos con ese trabajo hecho, que sirve como material educativo para que la gente vea una forma de hacer TDD. La implementación es libre. De hecho, caben varias implementaciones posibles. También puede ser que haya que modificar algunos tests para cambiar casos sencillos por casos más complejos, o que haya que añadir más test para cubrir bien todo lo que se quiere. Al final del todo, se invita a que se refactorice el código para que sea sostenible. Introduciendo principios de diseño, dentro de que el diseño sea simple.
Es un buen ejercicio para hablar de diseño de software y para probar diferentes patrones como “Value Object” y refactors como “Replace Conditional With Polymorphism”.
En el repositorio se incluye al menos una rama con una posible solución de implementación. Posiblemente vayamos agregando más ramas de soluciones. Si haces tu propia solución en un fork del repositorio, podemos luego incluirla como una rama de este.
Muchas gracias a todas las personas que asistieron al taller. Sabemos que se quedó mucha gente fuera porque se terminó el aforo. Esperamos que este pequeño artículo, junto con todas las instrucciones del repositorio permitan a cualquiera hacer el ejercicio. Como dije allí, pueden enviarnos sus soluciones si quieren recibir algo de feedback.
¿Quieres más? te invitamos a suscribirte a nuestro boletín para avisarte cada vez que recopilemos contenido de calidad que compartir.
Si disfrutas leyendo nuestro blog, ¿imaginas lo divertido que sería trabajar con nosotros? ¿te gustaría?
Pero espera 🖐 que tenemos un conflicto interno. A nosotros las newsletter nos parecen 💩👎👹 Por eso hemos creado la LEAN LISTA, la primera lista zen, disfrutona y que suena a rock y reggaeton del sector de la programación. Todos hemos recibido newsletters por encima de nuestras posibilidades 😅 por eso este es el compromiso de la Lean Lista