DISEÑO
DESARROLLAR UN PLAN DIFERENCIADO DE TEST DE DIFERENCIACIÓN PARA CADA ALTERNATIVA
TDD como metodología de
diseño de software
TDD o Test Driven Development es una práctica
de programación que consiste en escribir primero las pruebas (generalmente
unitarias), después escribir el código fuente que pase la prueba
satisfactoriamente y, por último, refactorizar el código escrito. Con esta práctica
se consigue entre otras cosas: un código más robusto, más seguro, más
mantenible y una mayor rapidez en el desarrollo.
TDD no es para hacer pruebas, es una práctica que
envuelve el desarrollo en su conjunto, especialmente el diseño de Software. De
hecho, algunos dicen que su última letra, debería significar diseño y no
desarrollo. Es decir, diseño orientado por las pruebas.
TDD Fue creado por Kent Beck (quien también inventó
Extreme Programming y JUnit), y en esencia, es un proceso a seguir, lo cual ya
lo hace diferente a un simple enfoque de pruebas primero.
Este ciclo también se lo conoce como rojo (hacer
que la prueba falle), verde (hacer que la prueba pase) y refactor. Aunque al
principio pueda parecer muy parecido a un enfoque de probar primero, al
combinarlo con practicas de desarrollo ágil, TDD toma un enfoque mucho más
amplio, y cambia su atención de las pruebas al diseño. TDD está mucho más
relacionado con el diseño emergente que con las pruebas, de hecho, que TDD
genere una gran cantidad de pruebas es un efecto secundario positivo, pero no
es su propósito final.
El proceso de diseño de software, combinando TDD
con metodologías ágiles, sería el siguiente:
1.
El cliente escribe su historia de usuario
2.
Se escriben junto con el cliente los criterios de
aceptación de esta historia, desglosándolos mucho para simplificarlos todo lo
posible
3.
Se escoge el criterio de aceptación más simple y se
traduce en una prueba unitaria
4.
Se comprueba que esta prueba falla
5.
Se escribe el código que hace pasar la prueba
6.
Se ejecutan todas las pruebas automatizadas
7.
Se refactoriza y se limpia el código
8.
Se vuelven a pasar todas las pruebas automatizadas
para comprobar que todo sigue funcionando
9.
Volvemos al punto 3 con los criterios de aceptación
que falten y repetimos el ciclo una y otra vez hasta completar nuestra
aplicación
un ejemplo práctico de este ciclo:
1.
Supongamos que el cliente nos pide que
desarrollemos una calculadora que sume números (es lo primero que se me ha ocurrido)
2.
Acordamos con el cliente que el criterio de
aceptación sería que si introduces en la calculadora dos números y le das a la
operación de suma, la calculadora te muestra el resultado de la suma en la
pantalla
3.
Partiendo de este criterio, comenzamos a definir el
funcionamiento del algoritmo de suma y convertimos el criterio de aceptación en
una prueba concreta, por ejemplo, un algoritmo que si introduces un 3 y un 5 te
devuelve un 8:
4.
public void testSuma() {
5.
assertEquals(8,
Calculadora.suma(3,5));
}
Este punto es para mi el
más importante de TDD y que supone un cambio de mentalidad, primero escribo
cómo debe funcionar mi programa y después, una vez lo tengo claro, paso a
codificarla.
Al escribir el test
estoy diseñando cómo va a funcionar el software, pienso que para cubrir la
prueba voy a necesitar una clase calculadora con una función que se llame suma
y que tenga dos parámetros. Esta clase todavía no existe pero cuando la cree,
ya se cómo va a funcionar. Este caso es muy trivial, pero muchas veces no
sabemos exactamente qué clases hacer o qué métodos ponerle exactamente. Es más,
muchas veces perdemos el tiempo haciendo métodos y clases que pensamos que
luego serán útiles, cuando la cruda realidad es que muchas veces no se van a
usar nunca. Con TDD sólo hacemos lo que realmente necesitamos en ese momento.
Realmente es la forma
natural de pensar, primero pensamos en Qué queremos hacer y después pasamos al
Cómo, la diferencia es que con TDD el test ya queda escrito y se ejecutará cada
vez que compilamos nuestro programa.
6.
Por supuesto, si intentamos pasar este test nos
dará un error, porque la clase Calculadora aún no existe.
7.
Ahora pasamos a escribir el código de la clase, es
fácil porque ya sabemos exactamente cómo se va a comportar:
8.
public class Calculadora {
9.
public static int suma (int a, int b) {
10.
int c = a + b;
11.
return
c;
12.
}
}
13.
Ahora ejecutamos la prueba y ya tenemos el código
funcionado con la prueba pasada.
14.
Una vez todo esté funcionando, pasamos a
refactorizar y a eliminar código duplicado, este ejemplo es extremadamente
sencillo, y en un caso real no haríamos tantos pasos para algo tan evidente,
pero el código mejorado podría ser por ejemplo:
15.
public class Calculadora {
16.
public static int suma (int a, int b) {
17.
return a+b;
18.
}
}
En ejemplos más
complejos, según vayamos escribiendo más test, deberíamos buscar código
duplicado y agruparlo en funciones o utilizar la herencia o el polimorfismo.
19.
Es importante pasar todos los test después de
refactorizar por si nos hemos cargado algo.
20.
Ahora deberíamos volver al punto 3 con tests más
complicados y repetir el proceso, por ejemplo, podíamos pasar a que el
algoritmo admita sumar números decimales, etc.
Esta forma de trabajar es también muy buena para
entender el código. Sabemos que la calidad del diseño de un software está
también relacionada con el conocimiento del equipo de desarrollo en relación al
dominio en cuestión. En este sentido, las pruebas son una muy buena forma de
entender el código y su funcionamiento, muchas veces incluso mejor que la
documentación.
También hay que decir que no todo es perfecto en
TDD, cuando llegue el momento de crear un test sobre la interfaz de la
calculadora la cosa se complica. Los puntos flojos que veo en TDD son:
·
Hay que utilizarlo y entenderlo bien para que sea
realmente productivo, te ayuda a centrarte en lo importante y a no
sobrediseñar, pero es importante saber refactorizar el código según vaya
evolucionando para que sea consistente.
·
Pruebas sobre interfaces gráficas. Aunque hay
soluciones parciales propuestas, para mi TDD solo funciona en la capa de
negocio, no encaja con interfaces visuales.
·
Bases de datos. Hacer pruebas de código que trabaja
con base de datos es complejo porque requiere generar unos datos conocidos
antes de hacer las pruebas y verificar que el contenido de la base de datos es
el esperado después de la prueba. Los objetos simulados (MockObjects) son otra
opción, pero personalmente creo que se pierde tiempo con esto.
BIBLIOGRAFIA
http://es.wikipedia.org/wiki/Desarrollo_guiado_por_pruebas
http://blogs.msmvps.com/lopez/2010/02/16/default-methods-in-ajsharp/






0 comentarios:
Publicar un comentario