Mariquita en la pantalla
Getting your Trinity Audio player ready...

Tras la introducción a TDD que tuvimos hace un tiempo, he creído conveniente ampliar un poco la información del anterior artículo, para exponer algunas anotaciones sobre esta técnica.

Si hacemos un repaso rápido, podemos recordar que con TDD tendremos los pasos siguientes (de forma resumida):

  • Análiza: antes de escribir el primer test, nos conviene estudiar que comportamiento deseamos probar, sus posibles entradas y salidas, restricciones, etc.
  • Escribir un test que falle: escribe un test que va a fallar. Ya sea porque falta código, o porque aunque ya existe parte de ese código aún no tiene todas las funcionalidades que se esperan de él.
  • Haz que el test pase: realiza los cambios mínimos para que el test pase correctamente.
  • Refactoriza: ahora puedes cambiar el código para mejorarlo. En este punto hay que probar todos los tests para asegurar que no se ha roto nada con el refactor.
  • Escribir el siguiente test que falle.

Una vez visto este mini-repaso, pasemos a realizar algunas anotaciones sobre TDD.

Anotación 1. Conjunto de datos de testing incompleto.

Uno de los puntos más importantes a tener en cuenta a la hora de trabajar con TDD, es tener un conjunto de datos de entrada y salida que nos dé la seguridad de tener todas las posibilidades probadas (al menos dentro de lo razonablemente posible). Y es que tener pocos datos, puede provocar que haya casos específicos que no sean correctos.

Como norma general deberíamos tener casos de prueba para lo siguientes tipos de datos:

  • Datos límite: esto es, el mínimo y máximo permitido. Aplicado a nivel de valores, parámetros de entrada variables, elementos en una lista, etc.
  • Datos erróneos: datos que podrían generar una excepción en el código.
  • Datos que difieran para cubrir lo máximo posible: por ejemplo, en el caso de que la entrada sea un usuario, podrían ser combinaciones dejando campos vacíos.
  • Datos que provoquen distintas lógicas: en el caso de una cesta de la compra, deberíamos tener pruebas con los distintos métodos de pago.

Anotación 2. Refactorizar dividiendo el código.

Puede que durante un refáctor de una clase o función con TDD, veas necesario separar la lógica, ya que el código ha crecido mucho y puede que esté comenzando a incumplir alguno de los principios SOLID.

Aquí tenemos dos posibilidades la lógica y un poco más costosa y la ilógica pero más rápida:

  • La opción lógica, sería comenzar a hacer TDD con esa nueva clase o función. Lo bueno es que puedes aprovechar seguramente parte de los casos que tienes y que afectaban al código que ibas a extraer. Así se mantiene todo el flujo de TDD, teniendo tests independientes para esta nueva parte.
  • La opción ilógica, implica seguir manteniendo los tests en el componente inicial para que prueben la otra parte. Es más rápido porque no requiere cambiar los tests, pero a cambio, tienes tests de una parte de tu código en otro elemento. Si este nuevo componente comienza a crecer, el mantenimiento comenzará a flaquear por todos lados, además de que no estarán bien organizados. Y recordemos que el código de tests, debe ser tan "limpio" como el código del proyecto.

Anotación 3. Actuación ante errores.

Pese a seguir la técnica de TDD, pueden surgir bugs, por ejemplo por casuísticas que no se habían tenido en cuenta. En este caso, no resuelvas el problema directamente. Añade un test con la lógica para provocar el fallo. Una vez hecho esto, comienza a corregir el código.

Anotación 4. Tests de código externo previo a una actualización.

En este caso, la técnica es parecida a la de la anotación anterior. Si vamos a actualizar un código externo (por ejemplo, una librería) y queremos usar una funcionalidad nueva. Nos podemos asegurar de que sabemos llamar a esa funcionalidad y que devuelve lo que esperamos, escribiendo primero un test que la intente usar. Posteriormente, actualizaremos la librería y probaremos de nuevo para ver si hemos entendido como funciona.

Crear tests para código externo también nos permite asegurarnos de que al actualizar la versión de éste, no rompe ninguno de los flujos y comportamientos que esperábamos. Como ejemplo: se cambia una entrada de la API pública y ahora pasa a ser obligatorio un parámetro que antes era opcional. Al actualizar la librería y lanzar los tests, todos aquellos que no pasen ese parámetro obligatorio se romperán. Gracias a ello, estaremos en preaviso de que no somos aún compatibles con esa versión.

En este caso, hablar de código externo daría casi para otro artículo.

Conclusiones.

TDD es una herramienta muy potente y permite cierta libertad a la hora de tomar algunas decisiones. Pero ello, no implica que usemos el martillo cogiendo la cabeza en lugar del mango. Es importante tener en cuenta los datos y la utilidad de los tests que estamos creando.

¿Qué opináis de TDD? ¿Ya os habéis "peleado" con él? ¿Hay consejos o anotaciones que echéis en falta?

Comparte este artículo con quien quieras
BDD y Gherkin. Una pequeña introducción
Caso práctico TDD

Leave a Comment

Your email address will not be published. Required fields are marked *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.