Está en la página 1de 30

Mtodos giles para el Desarrollo de Software

Trabajo Prctico Final


Test Driven Development (TDD)

Integrantes:
Ibaez, Rodrigo Sebastin Keimel, Marina Gisele Lizarralde, Ignacio Luna, Julia Elizabeth Tommasel, Antonela Vega, Maria Florencia Villavicencio, Christian Paulo

Tabla de contenido

Introduccin ...................................................................................................................................................... 2 Test-Driven Development ................................................................................................................................. 3 El ciclo de desarrollo TDD .................................................................................................................................. 4 Usando TDD: Caractersticas Importantes ........................................................................................................ 6 Deficiencias .................................................................................................................................................... 6 Beneficios ...................................................................................................................................................... 6 Diferencias entre TDD y otros modelos............................................................................................................. 8 Modelos de desarrollo de software evolutivos y TDD .................................................................................. 9 El ciclo TDD: Un pequeo ejemplo .................................................................................................................. 11 Perfeccionando el uso de TDD ........................................................................................................................ 14 TDD y Diseo ............................................................................................................................................... 14 Reusabilidad, Patrones de Diseo y TDD..................................................................................................... 14 Buenas prcticas al momento del desarrollo de los Tests .......................................................................... 14 Patrones de Testing Generales .................................................................................................................... 15 Patrones de Test Rojo.................................................................................................................................. 16 Patrones de Test Verde ............................................................................................................................... 17 Herramientas ................................................................................................................................................... 19 Familia xUnit ................................................................................................................................................ 19 Caractersticas comunes de la familia ......................................................................................................... 19 JUnit ............................................................................................................................................................. 20 Ejemplo de utilizacin de JUnit ............................................................................................................... 20 Boost ............................................................................................................................................................ 21 Utilizacin ................................................................................................................................................ 22 NUnit............................................................................................................................................................ 22 Funcionamiento ....................................................................................................................................... 23 Atributos .................................................................................................................................................. 23 Aserciones ............................................................................................................................................... 24 Adoptando TDD ............................................................................................................................................... 26 Fallas en la utilizacin de TDD ..................................................................................................................... 26 Conclusiones .................................................................................................................................................... 28 Bibliografa ....................................................................................................................................................... 29

Introduccin
La evolucin de los mtodos giles comenz a mediados de los 90. Antes a esto, el software era desarrollado centrndose en la planificacin del proyecto, un cuidadoso diseo y una extensa documentacin, lo que produca un importante overhead en proyectos no muy grandes. En mtodos giles dos de cada cuatro semanas son utilizadas como iteraciones. El objetivo de cada una de ellas es ofrecer software funcional, lo cual implica una planificacin cuidadosa, anlisis, diseo, implementacin y testing individuales. Especificar las entradas y salidas antes de programar la aplicacin concreta no es algo nuevo en el desarrollo de software, y TDD se basa en sta idea.

Test-Driven Development
[AEK09] [GEO02] [GEO03b] [WIL03] TDD es una prctica emergente que tiene su origen en Extreme Programming (XP), y que procura producir software de alta calidad rpidamente, sin desatender los cambios inevitables en los requerimientos y el diseo. Este mtodo de desarrollo de software se utiliza generalmente en procesos giles. Anteriormente, TDD fue llamado test-fist programming en comparacin a los mtodos de desarrollo tradicionales, en los cuales los tests se realizan luego de la implementacin del sistema. El problema con ese enfoque tradicional (llamado test-last programming) radica en que el cdigo no est preparado para ser testeado al trmino de su codificacin, incluso en aquellos casos en los que la testeabilidad constituye un atributo de calidad deseable del sistema. Cuando los tests son hechos antes que el cdigo a testear, el desarrollo de los mismos es guiado por los requerimientos y especificaciones del software; en el caso contrario, existe el riesgo de que los tests sean creados para satisfacer la implementacin, y no necesariamente los requerimientos. En TDD, la idea principal consiste en escribir los tests antes que el cdigo a ser testeado. El desarrollador entonces, trabaja agregando funcionalidad de a pequeos pasos, utilizando un framework de testing, que provee los mecanismos para la ejecucin de los test de unidad automticamente. El uso de esta prctica, adems, lleva a que los programadores implementen cdigo que de manera directa puede ser testeado automticamente; es decir, que se incluyan, por ejemplo, mtodos y funciones que devuelvan valores significativos para ser comparados con los resultados esperados. Los casos de test se van acumulando a travs de las iteraciones, formando una base que se utiliza como tests de regresin. stos se ejecutan continua y automticamente, lo que permite que se pueda determinar fcilmente si los nuevos cambios afectan negativamente la funcionalidad del sistema. Gracias a esto, TDD permite que cada nueva funcionalidad pueda ser integrada al sistema casi sin generar problemas. Otros beneficios del testing automticos incluyen: Produccin de un sistema confiable. Mejora en la calidad del testeo. Reduccin del esfuerzo a la hora del testing y minimizacin del programa.

El ciclo de desarrollo TDD


[AEK09] En todos los procesos existe una separacin entre la decisin (diseo) y el feedback de la misma (performance obtenida al implementar dicho diseo). El xito de TDD puede atribuirse al acortamiento de dicho espacio, o su completa eliminacin, dado que el ciclo dinmico seguido, test-then-code, provee un feedback constante y rpido.

La consigna de TDD, formulada por Beck, Rojo/Verde/Refactorizar, define su ciclo de desarrollo. En cada iteracin el desarrollador debe realizar pequeas decisiones de diseo e implementacin, e incrementar la funcionalidad (generalmente no ms de una pieza de funcionalidad por da laboral) a una taza relativamente consistente. Una regla importante es: "Si no puede escribir el test de lo que se est a punto de codificar, entonces no debera codificar en este momento". Partes del ciclo: Rojo: El primer paso del ciclo es, como ya se ha dicho, la creacin de tests fallidos. Estos tests son de caja blanca, ya que se hacen teniendo en cuenta cual ser la lgica interna del cdigo sobre el que ser utilizado. El hecho de que el test en un principio no funcione (e incluso podra no compilar) es importante, ya que la transicin de un estado al siguiente define el modo de verificacin de la implementacin. Verde: En el segundo paso se modifica el cdigo de forma simple y rpida para que pase el test. Esta solucin podra no ser eficiente e incurrir en repeticin de cdigo y malas prcticas. Hay que tener en cuenta que una nueva funcionalidad no es considerada propiamente implementada a menos que todos los test de unidad realizados para l, y todos los tests de unidad realizados durante todo el desarrollo del cdigo, resulten satisfactorios; es decir, que el nuevo cdigo no afecte funcionalidad anterior. Refactorizar: Finalmente, el tercer paso consiste en eliminar las repeticiones de cdigo y arreglar, en la medida de lo posible, el cdigo poco eficiente que haya sido implementado. El refactoring se define como transformacin que preserva el comportamiento, es decir, la reestructuracin del cdigo no debe modificar su funcionalidad externa. Para esto se pueden utilizar los mismos tests como soporte de 4

verificacin. La refactorizacin debe hacerse de a pequeos pasos para poder deshacer las acciones en caso de que se generen problemas. La ventaja principal de utilizar un ciclo tan dinmico viene desde el punto de vista del costo de cambio. Este conocido principio de la Ingeniera de Software dice que mientras ms tiempo permanezca un problema en el sistema de software, ms difcil y costoso ser eliminarlo. Como antes de agregar nueva funcionalidad se requiere que el sistema pase todos los tests histricos asociados a l, puede decirse que si en la siguiente iteracin surgen problemas, es muy probable que ese problema est indudablemente en el cdigo recientemente implementado, o en el que interacta inmediatamente con l. En consecuencia, los problemas son encontrados rpidamente, y su fuente puede ser fcilmente identificada. De todas maneras, cuando se encuentre tarde un defecto en el ciclo de desarrollo, se pueden escribir nuevos casos de test con la finalidad de exponer este defecto, antes de intentar arreglarlo.

Usando TDD: Caractersticas Importantes


Deficiencias
[GEO03a] Falta de Diseo. TDD generalmente no requiere un diseo de la arquitectura inicial, si bien algunas actividades relacionadas al mismo son realizadas de forma independiente al comienzo del desarrollo. Tener un diseo escaso o inexistente funciona en ciertos casos; a saber, cuando: 1. El equipo tiene un buen conocimiento del cdigo base. 2. El cdigo est en buena forma. De no existir alguna de estas precondiciones la aplicabilidad del mtodo en etapas posteriores queda limitada por la capacidad de comprensin de los programadores. Integridad Conceptual. En la prctica de TDD, ciertas tcnicas y notaciones propias del diseo de software, quedan integradas dentro del proceso de implementacin. Esto tiende a confundir, o a dificultar, la distincin entre ambas actividades; lo mismo sucede con las diferentes fases del desarrollo (diseo, cdigo y testing). Al focalizarse el proceso de implementacin en los elementos inmediatos que deben implementarse ms que en la estructura lgica; el uso de TDD podra tener como resultado la prdida, por parte de los programadores, de la macro estructura del sistema. Hight risk/high return. Si TDD es aplicado y el desarrollo concluye satisfactoriamente, entonces se dar lugar a un ahorro tanto de tiempo como de costos pero, en caso de una falla, al no haber un diseo explcito ni documentacin formal, no hay un respaldo sobre el cual apoyarse. Incluso, podran llegar a perderse las bases sobre las cuales se hayan tomado ciertas decisiones importantes. Aplicabilidad de la prctica. Ciertos tipos de sistemas son difciles de testear utilizando TDD, por ejemplo las interfaces con el usuario, cuyos tests no pueden necesariamente automatizarse. Habilidad de los programadores. Si el cdigo es difcil de testear, escribir el test para ello tambin resultar difcil, requiriendo un alto nivel de experiencia y determinacin por parte de los programadores. Si el equipo no cuenta con dicho nivel de habilidad, usualmente termina generndose cdigo sin casos de test o documentacin que identifique su comportamiento especfico.

Beneficios
[GEO02] [GEO03a] [WIL03] Comprensin del programa. El enfoque de TDD ayuda al entendimiento del cdigo, sobretodo en la etapa de mantenimiento, debido a que fomenta la explicacin del cdigo mediante casos de tests y el cdigo en s mismo; antes que una descripcin con palabras; asegurando, a su vez, que en todo momento los tests estn actualizados y su resultado es satisfactorio. Por otro lado, la prctica enfrenta la paradoja de que para entender una pieza de cdigo, el lector debe examinar, adems del mismo cdigo, otra pieza de cdigo (el test). Eficiencia. Como ya ha sido mencionado, la granularidad del ciclo test-then-code permite al desarrollador obtener un feedback constante, con lo cual, las fallas y/o problemas pueden ser identificados, junto a sus fuentes, en forma rpida y temprana. Base de Tests: La creacin de una base de tests que pueden ejecutarse automticamente, y que va incrementndose a lo largo del desarrollo, facilita la extensin y el mantenimiento del sistema. 6

Inyeccin de defectos. Durante la etapa de mantenimiento y debugging de un sistema, los problemas en el cdigo son generalmente emparchados, alterando efectivamente sus propiedades, pero sin examinar ni actualizar la especificacin y el diseo del sistema. Esto genera una cantidad de nuevos defectos en el cdigo. En caso de tener los tests de regresin a disposicin del programador, estos defectos pueden ser encontrados rpidamente, reduciendo as la posibilidad de que queden errores ocultos en el producto final. Diseo simple. Al no requerir ms diseo de lo que se ha implementado hasta el momento, que debera ser mnimo y simple, se asegura que ste tambin lo ser. Esto es generalmente bueno, ya que los diseos complejos tienden a ser defectivos.

Diferencias entre TDD y otros modelos


[GEO02] El enfoque de TDD difiere de otros enfoques de testing en dos aspectos principales. Primero, se desalienta el desarrollo de diseo de alto y bajo nivel antes de comenzar la implementacin, prefiriendo en cambio una modificacin-construccin constante del mismo a medida que el desarrollo progresa con el descubrimiento de nuevos objetos y condiciones. Esto resulta en numerosas ocasiones una ventaja, teniendo en cuenta que el diseo inicial no puede pensarse adecuadamente antes de la implementacin. La segunda diferencia es el grado en el cual el testing es realizado en TDD. Diversos modelos de desarrollo como V Model, especifican que el testing sea realizado en paralelo con la implementacin. Los posibles escenarios de los casos de testeo son pensados y las condiciones requeridas para pasarlos son incluidas en la implementacin. Luego, los casos de testeo se ejecutan para verificar que la implementacin sea correcta. En TDD, es proceso es llevado un paso ms adelante; los casos de testeo son realmente implementados de una forma incremental, asegurando que en un principio fallarn. Si esto no sucediera, entonces el caso de testeo se encuentra mal definido o la implementacin que pretende testear ya existe. El proceso de testing de unidad puede ser dividido en tres sub-fases: Diseo del testeo: qu debe verificarse y cmo. Implementacin del test. Ejecucin del test.

Modelo en cascada:

Cdigo

Diseo de los casos de test

Implementacin de los casos de test

Ejecucin de los casos de test

Modelo en V:

Diseo de los casos de test

Cdigo

Implementacin de los casos de test

Ejecucin de los casos de test

Modelo TDD:

Diseo de los casos de test

Implementacin de los casos de test

Cdigo

Ejecucin de los casos de test

En un modelo de cascada, todas las subfases del testeo de unidad ocurren luego de que el cdigo es escrito, mientras que en V-Model, el diseo de los casos de testeo ocurre antes de la implementacin; finalmente en TDD, el diseo y construccin de los casos de testeo ocurre antes de la implementacin.

Modelos de desarrollo de software evolutivos y TDD


[GEO02] Los modelos de desarrollo de software evolutivos, son iterativos por naturaleza. A menudo son utilizados cuando es deseable que el producto evolucione a lo largo del tiempo. Dado que TDD es tambin un enfoque iterativo que se desarrolla mediante la evolucin del producto a lo largo de un perodo de tiempo; comparte una gran cantidad de caractersticas con los procesos nombrados anteriormente aunque tambin poseen ciertas diferencias. Los procesos evolutivos, como por ejemplo, el modelo en espiral, tienen un diseo up-front y fases de anlisis de requerimientos en cada nivel del proyecto. Tambin, en algunos modelos, por ejemplo el incremental, el tiempo del ciclo de iteraciones es muy grande en comparacin con el enfoque TDD. El propsito de las iteraciones en los modelos evolutivos, es proveer un mecanismo de feedback al usuario y a los desarrolladores en lo que respecta a riesgos tcnicos y performance del producto. En TDD, dichos ciclos de feedback son ms reducidos gracias a una mayor granularidad del ciclo testeo-codificacin. Uno de los errores que puede cometerse durante el diseo de software es confundir las etapas del proyecto. Dado que en los diferentes modelos el ordenamiento de las etapas es en forma lineal o de ciclo; suele asumirse que de igual manera se deberan desarrollar las tareas. Como resultado, los diseadores se mueven entre diferentes niveles de abstraccin, desde asuntos referentes al dominio de aplicacin hasta detalles del cdigo de la implementacin. Este movimiento no es secuencial ni cclico y es iniciado por el reconocimiento de asuntos que pueden ocurrir en cualquier nivel de abstraccin. En TDD, dichos movimientos son ms explcitos, manifestndose en el hecho de que el diseo cambia de acuerdo al reconocimiento de necesidades. En el modelo en espiral, el prototipo desarrollado es continuamente mejorado a travs de las iteraciones. El enfoque de TDD es tambin similar a este, ya que ambos modelos pueden adaptarse para funcionar a lo largo de toda la vida del software, en comparacin con otros procesos que paran cuando el producto es terminado. Los modelos evolutivos, en particular el modelo en espiral, tienen sus propias limitaciones. Puede ser difcil de convencer al cliente de que los enfoques evolucionarios con controlables (teniendo en cuenta que los ciclos pueden ser desarrollados por siempre). Ms an, el modelo en espiral requiere una gran experiencia en el manejo de riesgos dado que a menos que sean descubiertos y manejados a tiempo, ocurrirn problemas.

En comparacin, los ciclos de iteracin de TDD son ms pequeos y se encuentran bien definidos. Adems, el manejo de riesgos no es un rea de foco en TDD, y es generalmente delegado a un proceso externo a l.

10

El ciclo TDD: Un pequeo ejemplo


[AEK09] Esta parte se centrar en explicar y describir el ciclo de TDD y el ritmo de trabajo, por medio de un pequeo ejemplo que ilustrar una simple aplicacin de calculadora que puede llevar a cabo la operacin de multiplicacin con nmeros enteros. En este sencillo ejemplo, donde la implementacin es obvia, los ir implementando de a pequeos pasos parece innecesario, pero cuando la funcionalidad compleja, ser capaz de dar pequeos pasos pueden ser esencial. El ejemplo muestra un test fallido, una aplicacin falsa y un desarrollo gradual de la implementacin. Ser programado utilizando C++ y el framework Boost de test de unidad. Una de las reglas bsicas de TDD es que ningn cdigo puede ser escrito antes de que haya un test de unidad fallido automatizado para probar la funcionalidad. El primer paso es entonces crear dicho test para la calculadora que provee la funcionalidad de multiplicacin. Dado que la clase calculadora no se ha implementado todava el test no se compilar. El compilador informa de que la clase Calculator no se puede encontrar y que la funcin de multiplicacin no est definida. Test de multiplicacin: CalculatorTest.cpp #define BOOST_TEST_MODULE calculatorTest #include <boost/test/unit_test.hpp> #include "Calculator.h" BOOST_AUTO_TEST_CASE(testMultiplication) { Calculator c; BOOST_CHECK_EQUAL(c.multiply(3, 5), 15); }

El siguiente paso es conseguir que el test compile de la forma ms sencilla posible. Para esto se agrega la clase Calculator y se implementa la funcin de multiplicar. La implementacin ms sencilla en este caso es devolver 0. Con esta implementacin, el test compila pero falla, dando el resultado deseado, ya que provee una forma concreta para medir el xito y el fracaso. Clase calculadora implementada de la forma ms sencilla posible: Calculator.h class Calculator { public: int multiply(int term_lhs, int term_rhs) { return 0; } };

11

El siguiente paso es llegar al estado verde, es decir, lograr pasar el test. Esto tambin debe hacerse en la forma ms fcil posible. En este caso, se falsificar el resultado devolviendo el valor 15 de forma constante. Es claro que esta no es la implementacin correcta, pero sirve para verificar que el test funciona. Implementacin falsificada de la calculadora: Calculator.h class Calculator { public: int multiply(int term_lhs, int term_rhs) { return 15; } };

En el paso anterior, se alcanz el estado verde en el ciclo de TDD. El siguiente paso es refactorizar el cdigo para obtener la implementacin correcta de la aplicacin. Esto se hace mediante la introduccin gradual de las variables para hacer la multiplicacin. Implementacin refactorizada para el test de la calculadora: Calculator.h class Calculator { public: int multiply(int term_lhs, int term_rhs) { return term_lhs * 5; } };

En el ejemplo anterior un valor constante fue cambiado por una variable. Cuando estos valores son quitados de la implementacin tests adicionales pueden ser realizados. Cuando se adicionan los nuevos test, la prueba falla y debe programarse la implementacin correcta. Test adicional de Calculadora: CalculatorTest.cpp #define BOOST_TEST_MODULE calculatorTest #include <boost/test/unit_test.hpp> #include "Calculator.h" BOOST_AUTO_TEST_CASE(testMultiplication) { Calculator c; BOOST_CHECK_EQUAL(c.multiply(7, 7), 49); }

12

En esta parte se ha descripto el ciclo de trabajo y el ritmo de TDD. Se ha demostrado cmo los test pueden ser escritos antes de la implementacin. El ejemplo era muy simple y los pequeos pasos no eran necesarios para un problema tan trivial, la implementacin podra haber sido realizada de manera directa. Los test se han aadido con ejecutados peridicamente durante el desarrollo del ciclo de TDD. Los test que produce el proceso de TDD es una documentacin de diseo de bajo nivel del sistema. Se encuentran escritos en un lenguaje que los programadores entienden. Cuando los test se ejecutan regularmente se asegura que la documentacin se mantiene actualizada.

13

Perfeccionando el uso de TDD


TDD y Diseo
[AEK09] [GEO02] TDD no es nicamente una tcnica de testeo, sino que tambin se sirve para realizar el anlisis y el diseo. Mientras se piensan y escriben los casos de testeo, es decir se analiza lo que el sistema har y no har se establece explcitamente el alcance del cdigo. Las mejoras de TDD en relacin con los mtodos tradicionales de testeo e implementacin, se encuentran en la insistencia explcita de escribir casos de test incrementales antes de implementar cdigo relacionado con las funcionalidades y un refactoring continuo, creando un test exhaustivo del software que se est desarrollando. En el momento en que los requerimientos cambian, el diseo se adapta para acomodarse a las nuevas especificaciones y solucionar los problemas surgidos. Una condicin para la existencia de un diseo cambiante es la refactorizacin del cdigo existente, es decir, la modificacin del mismo para dar solucin a los nuevos requerimientos. Cuando un test es escrito antes de que la implementacin, los desarrolladores estn obligados a pensar en la perspectiva de usabilidad y testeabilidad del programa. Esto resulta en que los programas estn diseados para ser ms fciles de utilizar y testear.

Reusabilidad, Patrones de Diseo y TDD


[GEO02] TDD realiza un enfoque prctico de la reutilizacin: En lugar de intentar predecir el futuro, espera hasta que la reusabilidad requerida se haga evidente y slo en ese momento se abstrae dentro del diseo. A pesar de que se realizan cambios tardos en el diseo, esto puede resultar ms eficiente dado que slo las abstracciones requeridas son incorporadas. Aunque TDD (escribir cdigo para las necesidades actuales) y los patrones de diseo (escribir cdigo para necesidades futuras) parecen conceptos contradictorios, pueden ser utilizados conjuntamente, haciendo uso de las habilidades de TDD, dar simplicidad al diseo y proveyendo un feedback continuo a las decisiones de diseo de los desarrolladores.

Buenas prcticas al momento del desarrollo de los Tests


[BEC02] Test de condicin nica. Cada test debe verificar una nica pieza de funcionalidad. Esto hace que los defectos en el cdigo sean ms fciles de encontrar. Los frameworks para testeo de unidad abortan un test si una asercin falla. En el caso en que un test verifica varias funcionalidades, este no ser ejecutado en forma completa si falla, por ejemplo, en la verificacin de la primera dejando el resto sin verificar. Las cosas simples como funciones de get y set no requieren test de unidad explcito; pero si contienen alguna lgica que por ejemplo, requiere inicializacin, un test debe ser realizado. Test aislados. 14

Los test no deben depender unos de otros para ser ejecutados. Para lograr test bajamente acoplados y cohesivos, estos no deberan requerir acceso a componentes externos (como ser, comunicaciones con una base de datos, redes o sistemas de archivos), ni algn tipo de configuracin manual antes de ser ejecutados. Test de rpida ejecucin. Si el conjunto de test toma demasiado tiempo en ejecutarse, existe el riesgo de que los desarrolladores no los ejecuten todos antes de realizar modificaciones. Buena Legibilidad. Los test escritos deben ser fciles de leer y entender. Su intencin debe ser tan clara como sea posible. Para ayudar a esto, los datos utilizados como entrada y salida tambin deberan ser claros, y ayudar al seguimiento de los tests. Datos Simblicos. Utilizar una nica constante para significar ms de un parmetro (por ejemplo, el mtodo suma(a,b) puede recibir las constantes 2 + 3, pero nunca 2 + 2). Datos Reales - Datos tomados de la realidad. Esta tcnica es til cuando se testean sistemas de tiempo real que utilizan estmulos de eventos externos obtenidos durante la ejecucin; cuando deben aparearse los resultados del sistema actual con aquellos de un sistema previo (testing paralelo); y en la refactorizacin de simulaciones que requieren siempre las mismas respuestas, especialmente cuando el problema puede recaer en la precisin de nmeros de punto flotante. Datos Evidentes: Incluir en el test tanto los resultados esperados como los obtenidos, haciendo su relacin evidente. Buena programacin. El cdigo de testing debe ser tratado como cdigo de produccin. Las mismas reglas de un buen diseo aplican a ambos, utilizando la refactorizacin cuando sea necesario.

Patrones de Testing Generales


[BEC02] Los patrones dados a continuacin son tcnicas ms detalladas para escribir los tests. Child Test. Si un caso de tests termina siendo demasiado grande y no hay manera de hacerlo funcionar, pueden escribirse tests ms pequeos que representen las partes del test grande que fallan. Al hacer funcionar los tests hijos, puede volver a introducirse el test grande. Mock Object. Para testear objetos que utilizan recursos de gran tamao o complicados, pueden crearse versiones falsas del recurso en cuestin que ayuden a resolver el problema actual. El ejemplo clsico son las bases de datos. Debido a que son grandes, toman demasiado tiempo para ser inicializadas y mantenidas y generalmente se encuentran en un servidor remoto. La mejor solucin en 15

estos casos es utilizar objetos que acten como la base de datos, pero que en realidad funcionan en memoria local. Self Shunt. Para testear la comunicacin entre objetos, lo mejor es hacer que el objeto testeado se comunique directamente con el caso de test, de modo de poder verificar as los resultados esperados de la comunicacin. Generalmente este patrn requiere que se utilicen interfaces para definir esta comunicacin, que el caso de test debera implementar. Log String. Para obtener un registro claro de la secuencia en que ciertos mensajes (operaciones) son llamados, se mantiene un registro en un string al que se agregan nombres cuando un mensaje es llamado. Este patrn suele utilizarse junto a Self Shunt. Crash Test Dummy. Ciertas partes del cdigo raramente son invocadas, por ejemplo, las excepciones. Para verificar que efectivamente stas funcionan, deberan ser invocadas utilizando objetos especiales cuya funcionalidad sea justamente esa. Un Crash Test Dummy es como un Mock Object, excepto que no se necesita construir el objeto completo, sino solo la parte sobre la que se quiere simular el error.

Patrones de Test Rojo


[BEC02] Estos patrones son tiles durante la primera etapa del ciclo de TDD, la escritura de los tests que fallan. One Step Test. Al comienzo de cada iteracin hay una cantidad de tests posibles a realizar. Conviene generalmente elegir un test que represente un claro avance, un paso hacia el objetivo global, y que uno del que se tenga la seguridad de poder implementar. Starter Test. Comenzar el desarrollo de una nueva funcionalidad testeando operaciones que en un principio no harn nada. Encontrar antes que nada, a donde pertenece dicha operacin. Explanation Test. Para extender el uso de los tests automticos, las explicaciones del cdigo del sistema deben ser formuladas y respondidas en trminos del testing. Learning Test. Cuando se trabaja sobre software externo (APIs, Cots, etc) conviene antes de su integracin escribir algunos tests simples que verifiquen que ste trabaja de la forma esperada. 16

Regression Test. Cuando se encuentra un defecto, lo primero que debe hacerse es escribir un test lo ms simple y pequeo que se pueda, que falle, y que una vez que sea satisfactorio, signifique que el defecto fue arreglado. Estos tests, de haber tenido un conocimiento perfecto de antemano, hubiesen sido creados en el momento de la produccin original. Muchas veces la aparicin de estos defectos indica que debe realizarse una refactorizacin del sistema.

Patrones de Test Verde


[BEC02] Las prcticas que se sugieren a continuacin representan una buena manera de hacer que el cdigo sortee con xito los test. Fake It ('Til You Make It). Antes de implementar el cdigo que dar una correcta solucin de la lgica requerida, se retorna una constante que devuelve el resultado esperado. Luego, con el test ya ejecutando en forma satisfactoria, se va transformando gradualmente dicha constante en una expresin que utiliza variables. Fake It ayuda psicolgicamente al equipo, porque al pasar de rojo a verde, se sabe en qu situacin se est, y es posible comenzar a refactorizar a partir de dicho punto. Otro factor es el control del ambiente, comenzar desde un ejemplo concreto y generalizar desde este previene la confusin con preocupaciones forneas. Pueden obtenerse mejores resultados si primero se resuelve el problema inmediato; de esta manera, cuando se quiera implementar el prximo caso de test, se puede poner el foco nicamente en l, dado que se sabe que el test anterior funciona. Triangulate. Al utilizar el patrn Fake It, queda poco claro en qu momento deben cambiarse las constantes por expresiones (abstraccin). La solucin queda en abstraer solamente cuando el test lo requiera (comienza a fallar), agregando asserts que triangulen cual es el resultado esperado. Sin embargo, hay que tener cuidado con la utilizacin de estas reglas, ya que pueden crear un ciclo infinito. Por ejemplo, si se tienen dos aserciones que han sido abstradas para la correcta implementacin de un mtodo, puede eliminarse una, dado que resulta completamente redundante. Si eso es realizado, se puede simplificar la implementacin del mtodo para que retorne solo una constante, con lo que se est volviendo al caso inicial. Obvious Implementation. En determinadas situaciones, lo mejor es simplemente implementar la operacin que se desea. Si la lgica requerida es suficientemente simple, no es necesario aplicar, por ejemplo, el patrn Fake It, sino directamente realizar la implementacin. Es preciso tener en cuenta los factores psicolgicos detrs de esta tcnica. Los seres humanos pueden ser muy sensibles ante los errores y justamente, el permitir que el desarrollador se gue por su conocimiento o experiencia y falle en algo demasiado simple, puede acarrear consecuencias muy negativas en su nimo o predisposicin. One to Many.

17

Para facilitar la implementacin de funcionalidad que trabaja con colecciones de objetos, se sugiere que en primera instancia se realice sin las colecciones y que luego se extienda para soportarlas.

18

Herramientas
Debido al gran xito que esta metodologa est teniendo en el mundo de la ingeniera del software, son muchas y variadas las herramientas que se han ido desarrollando hasta da de hoy. Algunas han surgido en forma de frameworks, otras en formato plug-in bajo el control de algn browser o incluso como libreras para su uso en plataformas de programacin. Quizs el formato en el que ms usado ha sido este tipo de metodologa haya sido el de los frameworks que consisten en entornos que facilitan la creacin, ejecucin y organizacin de pruebas unitarios. Todos los frameworks poseen sus propias funciones y atributos de clase de test que pueden ser utilizados para incluirlos en la plataforma de desarrollo utilizando el lenguaje correspondiente de forma que puedan ser manejados los test necesarios en cada momento.

Familia xUnit
[MES07] El trmino xUnit se refiere a cualquiera de los miembros de la familia de los Frameworks para testing de unidad, que comparten ciertas caractersticas comunes. La mayora de los lenguajes de programacin actuales usan por lo menos una implementacin de xUnit. Generalmente los tests son codificados en el mismo lenguaje que se est utilizando, y aunque no es estrictamente necesario, es una estrategia que facilita muchsimas cosas; no solo permite una conexin directa con la API, sino que requiere menos esfuerzo por parte de los programadores para la creacin de los tests.

Caractersticas comunes de la familia


[MES07]

Las caractersticas bsicas de los frameworks de tipo xUnit son: Entorno especializado. Dado un conjunto de mtodos de prueba, el framework proporciona una serie de test que se ejecutan devolviendo los resultados de una forma clara. SetUp o configuracin inicial. Para facilitar la creacin de tests compartidos, se pueden establecer una serie de reglas o mtodos que se ejecutan de forma previa al resto. Funciones predefinidas. Un framework, proporciona un conjunto de funciones prediseadas que permiten evaluaciones ms expresivas de acuerdo a las necesidades reales que pueden darse durante el flujo de una aplicacin. Proveen soporte para las siguientes tareas: Especificar un test como un Test Method Especificar los resultados esperados dentro del Test Method en forma de aserciones. Crear una agregacin de tests (test suites) que pueden correrse como una nica operacin. Ejecutar uno o ms tests para obtener un reporte con sus resultados.

19

JUnit
[BEC05] JUnit es un framework de testing de regresin para Java, en donde pueden escribirse tests de unidad durante el desarrollo del sistema. JUnit permite ejecutar los tests para verificar cuanto se desva el cdigo hecho de sus objetivos originales. El testing de integracin confirma que los diferentes subsistemas funcionan de manera correcta cuando son comunicados. El testing de aceptacin simplemente busca confirmar que la aplicacin haga lo que el cliente espera de l. Los tests de unidad son los que verifican una nica pieza de funcionamiento, que, en el caso de Java, podra tratarse de una clase. Hay una focalizacin fuerte sobre estos tests unitarios que verifican los bloques fundamentales de un sistema, de a uno a la vez, en lo que se denomina testing a nivel de mdulos. Esto lleva a un desarrollo de test suites que pueden ejecutarse en cualquier momento, asegurando que los cambios hechos en el cdigo y la refactorizacin no afectarn ninguno de los subsistemas de forma imprevista u oculta. Ejemplo de utilizacin de JUnit [BEC05]

Escribiendo un caso de test. Tanto en XP como en TDD, la consigna principal dicta que escribir y ejecutar tests debera ser fcil. Hacerlo con JUnit es tan simple como: 1. Crear una subclase de junit.framework.TestCase. 2. Crear un constructor que tenga por lo menos un parmetro String que indica su nombre, y que llame a super(name). 3. Implementar uno o ms mtodos que realizarn el testing. Estos mtodos no deben recibir ni devolver parmetros, y sus nombres deben comenzar con el prefijo test. En el siguiente ejemplo se crea el caso de test SimpleTest:
package org.example.antbook.junit; import junit.framework.TestCase; public class SimpleTest extends TestCase { public SimpleTest (String name) { super(name); } public void testSomething() { assertTrue(4 == (2 * 2)); } }

Ejecutando los casos de Test Las clases TestRunner, provistas por JUnit, se utilizan para ejecutar todos los tests que cumplan la condicin 3 dada anteriormente. 20

Los TestRunners ms populares son junit.textui.TestRunner y junit.swingui.TestRunner. El resultado de la ejecucin de un TestRunner por lnea de comandos, quedara de la siguiente manera:
java junit.textui.TestRunner org.example.antbook.junit.SimpleTest . Time: 0.01 OK (1 tests)

El punto (.) indica que el test se est ejecutando, y en este caso haba solamente uno, testSomething. Con el TestRunner Swing, se indica con verde que el test fue satisfactorio y rojo si fue fallido. Asercin de los resultados esperados El mecanismo por el cual JUnit determina si un test fue satisfactorio o no, es mediante las sentencias assert. Un assert es una simple comparacin entre un resultado esperado y el valor realmente obtenido. Hay algunas variantes entre los mtodos assert para cada tipo de dato primitivo, para los Strings y para los Objects, cada uno con los siguientes formatos: assertEquals(expected,actual), assertEquals(String message, expected, actual). Este tipo de asercin espera que expected.equals(actual) devuelva true, o que ambos objetos sean null. La asercin de equivalencia entre doubles permite adems especificar un rango, para evitar problemas con errores de punto flotante. assertNull(Object object), assertNull(String message, Object object). Verifica que el objeto al que hace referencia sea null. assertNotNull(Object object), assertNotNull(String message, Object). Verifica que el objeto al que hace referencia no sea null. assertSame(Object expected, Object actual), assertSame(String message, Object expected, Object actual). Esta asercin especifica una condicin ms estricta que equals, ya que compara la identidad de los objetos usando expected == actual. assertTrue(boolean condition), assertTrue(String message, boolean condition). La asercin falla si la condicin es falsa. fail(), fail(String message). Esta asercin siempre fuerza a que el caso de test falle, esto es til para cerrar caminos hacia parte del cdigo que no debera alcanzarse.

Boost
[BOO11] El Framework de Test de Unidad Boost Test Library provee una automatizacin del testing fcil y flexible en C++, ayudando en la implementacin y organizacin de los test de unidad. Especficamente provee facilidades verstiles para: Simplificar la implementacin de los tests mediante la utilizacin de diferentes herramientas de testing. Organizar los casos de test en arboles de test. Reportar el procesamiento de parmetros en tiempo de ejecucin.

21

El Framework mantiene un seguimiento de todas las aserciones satisfactorias/fallidas, provee verificacin del progreso del testing y genera un reporte con los resultados en diferentes formatos. Para la ejecucin, se proveen test runners para lnea de comandos que pueden inicializar y correr los tests requeridos. Dependiendo de las opciones de compilacin seleccionadas, una implementacin por defecto de la funcin main() puede generarse automticamente. Utilizacin La funcin main es la responsable de la inicializacin del ambiente y de la creacin de reportes. Adems, incluye una comunicacin con el usuario por la que puede ingresarse informacin necesaria. Para integrar un test al framework debera proveerse la siguiente funcin:

boost::unit_test::test_suite* init_unit_test_suite ( int argc, char* argv[] )

Su principal responsabilidad es la de crear e inicializar el rbol de tests, que consiste en casos de test y test suites. Ejemplo: void my_test_function() { ... } test_suite* init_unit_test_suite( int argc, char* argv[] ) { test_suite* test = BOOST_TEST_SUITE( "Master test suite" ); test->add( BOOST_TEST_CASE( &my_test_function ) ); return test; }

NUnit
[NUN11] Se trata de un framework opensource para pruebas unitarias de sistemas realizados con la plataforma Microsoft .Net. Es un framework desarrollado en C#. Utiliza atributos personalizados para interpretar las pruebas y provee adems mtodos para implementarlas. En general, NUnit compara valores esperados y valores generados, si estos son diferentes la prueba no pasa, caso contrario la prueba es exitosa. Algunas de las caractersticas de este framework son: 22

Pruebas de unidad para lenguajes.NET y Mono. Provee un ainterfaz grfica para ejecutar las pruebas. Sigue el modelo JUnit. Integracin con Visual Studio en cualquiera de sus versiones soporte de archivos de configuracion Es extensible Autodetecta cambios de los ensamblados Extensiones: o NUnit.Forms o Pruebas de elementos de los interfaces de usuario en Windows Forms. o NUnit.ASP o Pruebas de elementos en ASP.NET

Funcionamiento NUnit basa su funcionamiento en dos aspectos, el primero es la utilizacin de atributos personalizados que le indican al framework de NUnit qu es lo debe hacer con determinado mtodo o clase, es decir, estos atributos le indican a NUnit como interpretar y ejecutar las pruebas implementadas en el mtodo o clase. El segundo son las aserciones, que son mtodos del framework de NUnit utilizados para comprobar y comparar valores. Atributos La versin 1x de NUnit utilizaba las convenciones de nombrado del framework de .NET, pero desde la versin 2 en adelante NUnit usa atributos personalizados. Dado que el framework de NUnit no deriva de otra clase o framework, el desarrollador puede elegir libremente el nombre de la prueba. TestFixture

Este atributo se utiliza para indicar que una clase contiene mtodos de prueba. En versiones anteriores para poder utilizar este atributo se deba extender (heredar de) la clase TestCase,mientras que, a partir de la versin 2, esto no es necesario, situacin que hace mucho ms flexible el uso del atributo. De todas maneras, existen algunas restricciones, como por ejemplo que la clase debe tener un constructor por defecto y debe ser publica para que el framework NUnit pueda accederla. ExpectedException

Este atributo como su nombre lo sugiere, tiene como funcionalidad indicar que la ejecucin de un mtodo prueba va a lanzar una excepcin. El atributo tiene como parmetro el tipo de excepcin que se espera que lance el mtodo, el framework ejecuta la prueba y si se genera una excepcin del tipo especificado entonces la prueba es exitosa, si por el contrario se genera una excepcin de tipo diferente al especifico la prueba no lo es. La excepcin debe ser exactamente la especificada en el parmetro del atributo

23

Suite

El atributo suite es utilizado para definir subconjuntos de pruebas de acuerdo a las preferencias del usuario, sin embargo este atributo ha sido reemplazado desde la versin 2 debido al nuevo mecanismo dinmico de ejecucin de pruebas del framework (en modo grfico se puede seleccionar qu pruebas se desean ejecutar utilizando el atributo category, adems se pueden agrupar dentro de una estructura marcada como TestFixture). En general es soportada para proveer compatibilidad hacia atrs. En las nuevas versiones del producto no se puede correr suites. Category

El atributo category provee una alternativa a las suites para trabajar con grupos de pruebas. Cualquiera, ya sea casos de prueba individuales o Fixtures, pueden ser identificadas como pertenecientes a una categora de pruebas en particular. Ya sea en modo grafico o en modo consola se puede especificar que categoras se excluyen o incluyen en la ejecucin. Cuando se utilizan categoras, solo las pruebas de la categora seleccionada son ejecutadas. Las pruebas incluidas en las categoras que se excluyen de la ejecucin no son reportadas. Para excluir o incluir determinada categora en el modo consola incluya el parmetro /exclude o /include seguido del nombre de la categora. En el modo grfico existe una pestaa denominada categoras. Es importante anotar que esta funcionalidad solo se encuentra presente en la versin 2.2 del producto. Este atributo puede utilizarse junto con TextFixture o Test Explicit

Este atributo ocasiona que una prueba o un Fixture sean ignorados por el programa y no sean ejecutados a menos que se especifique lo contrario. Si una prueba o un Fixture con el atributo Explicit es encontrado durante la ejecucin, el programa la ignora. El icono de la prueba o el Fixtures se coloca amarillo y es colocado en el reporte de pruebas no ejecutadas. Esto es til cuando se desea, por ejemplo no ejecutar todas las pruebas sino una seleccin de ellas. Las pruebas marcadas con Explicit pueden ser ejecutadas si explcitamente se le indica al programa que lo haga y esto se hace seleccionando la prueba y oprimiendo el botn run en el entorno grfico o escribindola en la ventana de comandos. Ignore

Utilizado para indicar que se debe ignorar determinada prueba o Fixture, El programa ve el atributo y no ejecuta la prueba o pruebas. El icono se coloca amarillo y la prueba es reportada como no ejecutada. Esto es til para inhabilitar pruebas temporalmente, es decir, este atributo es til para marcar una prueba o Fixture, si no se desea ejecutarla momentneamente, en vez de comentar el mtodo o la clase, ya que de todas maneras va a ser compilada junto con el resto del cdigo pero no ser tenida encuentra a la hora de ejecutar las pruebas. Aserciones Las aserciones son mtodos estticos que la clase assert provee para realizar comparaciones y condiciones de prueba. Las aserciones ms utilizadas son las de comparacin, stas reportan tanto el valor esperado como el valor actual. El valor esperado es siempre el primer parmetro en un mtodo assert, por ejemplo: Assert.AreSame(object expected, object actual, string message ); 24

En general se tiene dos mtodos sobrecargados: Assert.AreSame y AssertAreEqual, el primero verifica que el mismo objeto est referenciado por ambos argumentos, es decir que las dos referencias a objetos apunten al mismo objeto, por ejemplo: Assert.AreEqual (int expected, int actual, string message ); El Segundo esta sobrecargado para trabajar con la mayora de los tipos comunes(int, integer, double, single, string, etc.), por ejemplo: Assert.AreEqual(string expected, string actual, string message ); En una prxima versin se podr comparar arreglos. Es importante destacar que los mtodos sobrecargados proveen la funcionalidad de comparar objetos de diferentes tipos y obtener el resultado apropiado, por ejemplo la siguiente prueba es exitosa: Assert.AreEqual(3, 3.0, Son Iguales );

25

Adoptando TDD
[AEK09] [AST03] Para la adopcin del TDD se requiere que el desarrollador aprenda nuevas tcnicas de desarrollo de software y por lo menos del manejo de una herramienta. Esta nueva herramienta es obligatoria y se trata de un framework de testeo de unidad. El aprendizaje de una nueva herramienta reduce la productividad y calidad al comienzo. Hay un esfuerzo por aprender y entender nuevas ideas y para ver como esto se adapta al entorno de desarrollo actual. En el primer proyecto donde se utiliza una nueva herramienta o tcnica, los desarrolladores son menos efectivos, lo que hace que ste tome ms tiempo que el usual. El beneficio real de una nueva idea no es ganado hasta que la curva de aprendizaje es superada. Es difcil decir en trminos generales cuanto tiempo tomar; pero para obtener un mayor beneficio al final, mayor ser la curva de aprendizaje. La longitud de dicha curva y la grandeza del beneficio puede ser estimada preguntndole a alguien que ya se encuentre utilizando la misma tcnica o herramienta. La respuesta del especialista debe ser crticamente evaluada, dado que la persona puede tener intereses sobre el producto por el cual le fue consultado. Pair programming es un mtodo de desarrollo de software gil que tiene su origen en XP. Significa que dos personas trabajan juntas en una nica computadora. Este mtodo puede ser utilizado para aliviar la curva de aprendizaje del equipo. Es ms fcil disciplinar en la escritura de test cuando se est trabajando con alguien ms. Aprender TDD sin un entrenamiento externo puede ser difcil. El equipo puede ser mandado a seminarios externos o cursos de entrenamiento. La persona a cargo de los mismos debe tener experiencia prctica en el mtodo de TDD y ser capaz de ensear al equipo enfocndose en los aspectos prcticos, por ejemplo, a travs de pair programming como se ha mencionado anteriormente. En la aplicacin del mtodo pueden surgir una gran cantidad de problemas. Por ejemplo, los desarrolladores pueden encontrar difcil llevar a la prctica el TDD en partes complejas del sistema y en la escritura de tests para cada una de las partes del cdigo fuente. Otras limitaciones, pueden referirse a los frameworks de testeo de unidad. Las aplicaciones con interfaz grfica son difciles de testear. Por otra parte, los desarrolladores pueden tender a abandonar la escritura de tests de unidad durante los perodos de tiempo cercanos al lmite de entrega, dado que consideran ms importante completar todas las caractersticas que le fueron solicitadas entregando las funcionalidades prometidas.

Fallas en la utilizacin de TDD


[AEK09] [AST03] Para comenzar a utilizar TDD se requiere que todo el equipo de trabajo se encuentre comprometido. Si una persona rompe un test, es mucho ms fcil para otra tambin hacerlo. Los desarrolladores deben estar acostumbrados a arreglar los test que fallan, an si se trata en cdigo que algn otro ha escrito y es parte de un sistema con el que no se est familiarizado. Para ello, se necesita que el equipo trate al cdigo como si fuera de propiedad colectiva. Los desarrolladores prefieren programar en favor del testing y tienden a escribir test incompletos que nicamente prueban escenarios sencillos. De esta manera, partes crticas del sistema que son difciles de testear son probadas con test pobremente escritos.

26

La adopcin del mtodo debe ser positiva para los desarrolladores, su beneficio debe estar claro. Si el equipo de desarrollo de software no se da cuenta del porqu de los beneficios del TDD, es probable que su utilizacin falle.

27

Conclusiones
TDD es una prctica emergente que tiene su origen en Extreme Programming (XP), y que procura producir software de alta calidad rpidamente, sin desatender los cambios inevitables en los requerimientos y el diseo. Este mtodo de desarrollo de software se utiliza generalmente en procesos giles. Los tests de unidad creados como parte del TDD constituyen una herramienta poderosa que debe ser utilizada. Mejora la calidad del software en una forma que agrega valor al negocio. Para adoptar completamente TDD y utilizarlo como un mtodo de diseo y desarrollo, es posible encontrar ciertos obstculos debido a la diferencia en su naturaleza respecto a las maneras tradicionales de desarrollo. Dicha adopcin requerir la predisposicin y el entendimiento de cada uno de los individuos que se encargarn del desarrollo.

Puede concluirse que TDD tiene potencial y que debe ser seriamente evaluado en la prctica para su utilizacin pero sin perder de vista las necesidades concretas del software a desarrollar y las posibilidades de adaptacin del equipo de desarrollo.

28

Bibliografa
[AEK09] Aekmelaeus, W. Test-Driven Development. Arcada University of Applied Sciences. Helsinki 2009. [AST03] Astels, D. Test-Driven Development: A Practical Guide. Pearson Education. 2003. ISBN 0-13-101649-0 [BEC02] Beck, K. Test Driven Development: By Example. Addison-Wesley Longman. 2002. ISBN 0321146530 [BEC05] Beck, K.; Andres, C. Extreme Programming Explained: Embrace Change (2nd Edition). Addison Wesley
2005. ISBN 0-321-27865-8

[BOO11] Boost Test Library: Unit Test Framework http://www.boost.org/doc/libs/1_35_0/libs/test/doc/components/utf/index.html. Accedida 24 de Octubre de 2011. [FRE09] Freeman, S.; Pryce, N. Growing Object-Oriented Software, Guided by Tests. Addison Wesley. 2009. ISBN-13: 9780321503626 [GEO02] George, B. Analysis and Quantification of Test Driven Development Approach. A thesis submitted to the Graduate Faculty of North Carolina State University in partial fulfillment of the requirements for the Degree of Master of Science. Raleigh 2002. [GEO03a] George, B.; Wiiliams, L. A structured experiment of test-driven development. Elsevier B.V. 2003. [GEO03b] George, B.; Williams, L. An Initial Investigation of Test Driven Development in Industry. Proceedings
of the 2003 ACM symposium on Applied computing. ISBN:1-58113-624-2

[KAR07] Karlesky, M.; Williams, G.; Bereza, W.; Fletcher, M. Mocking the Embedded World: Test-Driven Development, Continuous Integration, and Design Patterns. Embedded Systems Conference Silicon Valley (San Jose, California) ESC 413, April 2007 [KAU03] Kaufman, R.; Janzen, D. Implications of Test-Driven Development A Pilot Study. OOPSLA '03 Companion of the 18th annual ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications. 2003. ISBN:158113-751-6

[MAD10] Madeyski, L. Test-Driven Development An Empirical Evaluation of Agile Practice. Springer Heidelberg Dordrecht London New York. 2010. ISBN 978-3-642-04287-4 [MES07] Meszaros, G. xUnit Test Patterns - Refactoring Test Code. Addison-Wesley. 2007. ISBN 13: 978-013-149505-0 [NUN11]NUnit.org Home Documentation http://www.nunit.org. Accedida 24 de Octubre de 2011. [WIL03] Williams, L; Maximilien, M; Vouk, M. Test-Driven Development as a Defect-Reduction Practice. 14th International Symposium on Software Reliability Engineering. 2003. ISBN: 0-7695-2007-3

29