Primeros pasos con TDD
Hoy he comenzado a leer Test-Driven Development in Microsoft.NET de MSPress, y la idea de este Post es resumir la introducción y el Capitulo 1 “Test-Driven Development Practices”
Introducción:
No todo en TDD es el testeo de software. El principal objetivo de TDD es ayudar al programador y al cliente en el proceso del desarrollo con requerimientos inciertos o dudosos.
Es importante que los problemas se descubran lo antes posible y sean corregidos cuando estos se encuentren. Frecuentemente los problemas ocurren por desacuerdos entre el cliente y los que producen el software. Esto se puede evitar especificando requerimientos que puedan ser interpretados de diferentes formas antes de comenzar el desarrollo. Estos test deben especificarse de tal forma que no requieran intervención de una persona para indicar si han sido correctos o erróneos.
Los test no solo sirven para el proceso de desarrollo, también es interesante aplicarlos una vez que el producto este en producción, y por ejemplo si se detecta un error lo primero que debemos hacer es escribir un test para identificar el problema y luego de obtener un test fallido, solucionar el problema.
Si tenemos suficientemente cubierto nuestro desarrollo con tests esto nos permitirá en un futuro poder añadir nuevas funcionalidades quitándonos el miedo de que surjan errores, y que éste miedo provoque que nos retrasemos.
Reglas principales
Nunca escribir una sola línea de código a menos que tengas un test automatizado que falle.
Eliminar código duplicado. En Extreme Programing esto esta regla se llama “Once and Only Once!” (Una vez y solamente una vez)
Tipos de Test
Test de programador (technology facing or programmer tests): Puede estar escrito en diferentes lenguajes, la herramienta que se suele usar es NUnit
Test del cliente (acceptance tests or functional tests): Deben estar especificado de tal forma que el cliente pueda entenderlo. La idea es conseguir que el cliente pueda escribir estos test. Una herramienta que se puede usar es Framework for Integrated Test (FIT)
Diseño simple
El código escrito debe satisfacer los requerimientos de forma mínima para que el proyecto funcione correctamente, pero no se debe añadir funcionalidades de más, que no están especificadas en los requerimientos, porque esto conllevará una carga de mantenimiento innecesaria.
Por lo tanto lo que debemos procurar es lo siguiente:
- El código es apropiado y entendible para otros programadores
- El código pasa todos los tests
- El código comunica todo lo que necesita
- El código tiene el menor número de clases
- El código tiene el menor número de métodos
Refactorizar :
Significa mejorar el código y que éste no cambia su funcionalidad. Esta es una parte crítica de TDD ya mientras refinas el código necesitas ir añadiendo test adicionales.
Procesos:
Lista de Tests:
Al comenzar una nueva lista de tareas o características, lo importante es idear una buena cantidad de pruebas a realizar. Y tal como las vamos pensando debemos ir escribiéndolas. Además de describir de forma clara los requerimientos, esta lista nos ayudará a determinar el alcance de la actividad que estemos planteando y será la definición más completa para el objetivo que deseemos alcanzar.
El tiempo aproximado que debemos utilizar para realizar estas actividades será de 15-20 minutos por cada 4 horas de trabajo que nos determine la tarea que realicemos.
Una vez completada esta lista, debemos elegir cuál es el test más significativo que vamos a utilizar, éste será el que mayor información nos brinde acerca del problema que hemos planteado, y así ejecutaremos todos los tests hasta terminar.
Red/Green/Refactor:
Define el proceso a seguir para implementar cada uno de los tests que hayamos definido. Lo interesante de todo esto es que estaremos trabajando con pequeños trozos de trabajo de forma organizada, lo que nos brindará una información más precisa mientras estemos codificando.
La lista a seguir es la siguiente:
- Escribir el código del test
- Compilarlo (el cual fallará porque no hemos codificado ninguna funcionalidad)
- Codificar lo suficiente para poder compilar
- Ejecutar el test para ver si falla
- Codificar lo suficiente para que el test pase
- Refactorizar para eliminar duplicados y obtener mayor claridad en nuestro código
- Ejecutar todos los test nuevamente
Por más tonta que parezca esta lista, es importante realizarlo de esta forma, tan simple y paso a paso, porque será lo que nos permita detectar los errores en el preciso instante que se produzcan mientras los estemos codificando, lo cual nos evitará tener que utilizar el debugger (depurador).
Gracias a esto vamos a notar que los tiempos de codificación serán mucho menores ya que tendremos la certeza y la confianza que nuestro código no va a fallar. Esta confianza es el resultado de la información que iremos recibiendo mientras ejecutemos los tests.
En el próximo post intentaré ejemplificar esto para que se vea un poco más claro.
Juan Pablo Garcia Blog