25 mayo 2006
TDD y Eclipse
En nuestro trabajo diario intentamos desarrollar siguiendo las prácticas de eXtreme Programming, y entre ellas en especial el desarrollo guiado por pruebas o TDD. Y digo "intentamos" porque a veces no es fácil aplicar TDD para corregir bugs o trabajar con código que ya está escrito. Sin embargo, TDD funciona extraordinariamente bien para desarrollar nuevas clases, sobretodo si trabajas con Eclipse.
Vamos a poner un ejemplo tonto: tenemos que desarrollar la clase "Device", que entre otras cosas, tiene un identificador, una descripción, un constructor de copia y un método que nos dice si el dispositivo soporta un formato específico de audio (basándonos en una base de datos en UAProf o WURLF).
Podemos abordar este problema de tres formas distintas:

Empezamos codificando el esqueleto típico de la clase de pruebas con JUnit, y vemos como Eclipse nos marca una serie de errores de compilación. Como vemos en la imagen de la derecha, nos dice que la clase "Device" no se ha encontrado (logicamente, porque todavía no existe :). Haciendo clic sobre la marca de error del margen izquierdo, nos aparece una lista con posibles soluciones al error, y entre ellas: crear la clase. Así que dejamos que Eclipse cree el esqueleto de la clase "Device", y seguimos con nuestras pruebas.
Después de codificar dos métodos de pruebas estamos en las mismas: tenemos varios errores de compilación, ya que estamos llamando a métodos que todavía no existen.
Por ejemplo, en el test que prueba el constructor de copia, estamos llamando a un constructor que todavía no existe (además de un par de los getter), así que hacemos clic sobre la marca de error, y seleccionamos la opción "Create constructor Device(Device)". Con el resto de errores de compilación podemos hacer lo mismo, aunque habrá casos en que tendremos que completar o cambiar el tipo a ciertos parámetros que Eclipse no es capaz de deducir.
De este modo, casi podemos hacer que Eclipse nos vaya generando el esqueleto de nuestra clase de lógica basándose en las llamadas que hacemos desde la clase de pruebas.
Esto nos puede ahorrar bastante tiempo que dedicamos sólo a tareas de códificación zombie (la que se hace sin pensar, sólo para que los compiladores nos dejen vivir en paz).
Una vez que tenemos la prueba completa y el esqueleto de la lógica, podemos seguir codificando la lógica de la clase, hasta que todos los test pasen correctamente (aunque creo que Eclipse no puede ayudarnos demasiado en esto).
Vamos a poner un ejemplo tonto: tenemos que desarrollar la clase "Device", que entre otras cosas, tiene un identificador, una descripción, un constructor de copia y un método que nos dice si el dispositivo soporta un formato específico de audio (basándonos en una base de datos en UAProf o WURLF).
Podemos abordar este problema de tres formas distintas:
- La forma tradicional de hacerlo sería directamente: se codifica la clase, se usa desde donde sea, y los errores que se vayan detectando se corrigen como se puedan.
- Otra forma es codificando la clase y después programando un test unitario sobre esa clase. Hay un montón de frameworks que nos ayudan a programar test unitarios, aunque en nuestro caso usamos JUnit y J2MEUnit.
- Y por último, como decía Félix, podemos empezar la casa por el tejado y aplicar la metodología TDD: codificando primero las pruebas y después la lógica. Aviso que hay situaciones donde esto no tiene mucho sentido, y otras donde hacerlo así nos puede aclarar mucho la mente. Por ejemplo, si tienes muy claro el interfaz público que va a tener tu clase (porque ya has desarrollado antes algo parecido, o porque vienes de un diseño muy detallado), quizá no necesites codificar antes las pruebas. Sin embargo, si no tienes muy claro cómo va a ser la clase que tienes que hacer, empieza por las pruebas y verás como el resultado es mejor de lo que esperabas.

Empezamos codificando el esqueleto típico de la clase de pruebas con JUnit, y vemos como Eclipse nos marca una serie de errores de compilación. Como vemos en la imagen de la derecha, nos dice que la clase "Device" no se ha encontrado (logicamente, porque todavía no existe :). Haciendo clic sobre la marca de error del margen izquierdo, nos aparece una lista con posibles soluciones al error, y entre ellas: crear la clase. Así que dejamos que Eclipse cree el esqueleto de la clase "Device", y seguimos con nuestras pruebas.
Después de codificar dos métodos de pruebas estamos en las mismas: tenemos varios errores de compilación, ya que estamos llamando a métodos que todavía no existen.

Por ejemplo, en el test que prueba el constructor de copia, estamos llamando a un constructor que todavía no existe (además de un par de los getter), así que hacemos clic sobre la marca de error, y seleccionamos la opción "Create constructor Device(Device)". Con el resto de errores de compilación podemos hacer lo mismo, aunque habrá casos en que tendremos que completar o cambiar el tipo a ciertos parámetros que Eclipse no es capaz de deducir.
De este modo, casi podemos hacer que Eclipse nos vaya generando el esqueleto de nuestra clase de lógica basándose en las llamadas que hacemos desde la clase de pruebas.
Esto nos puede ahorrar bastante tiempo que dedicamos sólo a tareas de códificación zombie (la que se hace sin pensar, sólo para que los compiladores nos dejen vivir en paz).
Una vez que tenemos la prueba completa y el esqueleto de la lógica, podemos seguir codificando la lógica de la clase, hasta que todos los test pasen correctamente (aunque creo que Eclipse no puede ayudarnos demasiado en esto).
Etiquetas: agile, j2me, programación, TDD