2. Test DrivenDevelopment Es una práctica de programación que involucra a su vez otras dos prácticas: Escribir primero las pruebas (Test FirstDevelopment) Refactorización (Refactoring) 2
3. TDD (2) En primer lugar se escribe una prueba, y se verifica que la prueba falle. Luego se implementa el código que haga que la prueba pase satisfactoriamente. Seguidamente, se refactoriza el código escrito. Para escribir las pruebas generalmente se utilizan las pruebas unitarias. 3
4. Características de TDD TDD facilita un diseño más mantenible a través de la noción de pruebas. Estas pruebas obligan a reflexionar sobre el comportamiento del código y la forma de garantizar que funciona según lo previsto. La mayoría de las veces, el código influenciado por TDD es relativamente seguro, y bastante simple. 4
5. Características de TDD (2) El código que es seguro y simple es más fácil de cambiar que el código que muestra los rasgos opuestos, como la complejidad y fragilidad. Además, como el código de TDD se respalda con pruebas, cualquier cambio que rompe el código se descubre fácilmente. El código escrito usando TDD es más fácil de cambiar y más fácil de arreglar. 5
6. Características de TDD (3) TDD no trata de que los cambios sean fáciles, al menos no directamente. TDD tiene que ver con la velocidad. Cuando los equipos ejecutan TDD consistentemente en sus mentes, las características del software se producen con mayor rapidez. 6
7. Propósito de TDD El propósito de TDD es especificación y no validación. En otras palabras, es una forma en que pensemos en los requerimientos o diseño antes de que escribamos código funcional. Es primeramente una técnica de diseño con el efecto secundario de asegurarse de que el código fuente esté probado a fondo 7
8. Pilares de TDD La implementación de las funciones justas que el cliente necesita y no más. La minimización del número de defectos que llegan al software en fase de producción. La producción de software modular, altamente reutilizable y preparado para el cambio. 8
9. Razones para el uso de TDD La calidad del software aumenta. Se consigue código reutilizable. El trabajo en equipo se hace más fácil. Permite confiar en los compañeros, aunque tengan menos experiencia. Multiplica la comunicación entre los miembros del equipo. 9
10. Razones para el uso de TDD (2) Las personas encargadas de la garantía de la calidad adquieren un rol más inteligente e interesante. Escribir la prueba antes que el código nos obliga a escribir el mínimo necesario de funcionalidad evitando sobre-diseñar. Al ver las pruebas, estas sirven de ejemplo o documentación técnica para entender el funcionamiento de cada parte del sistema 10
11. El Proceso de TDD El proceso de TDD consta de solo 3 pasos: Escribir la especificación del requisito (la prueba) Implementar el código que haga que la prueba pase. Refactorizar para eliminar duplicidad y hacer mejoras. 11
12. Escribir la Especificación del Requisito Cuando se tiene claro el requisito, este debe ser expresado en forma de código (se escribe el código de la prueba). Como el elemento que se está probando, llamado SUT (SubjectUnder Test) aún no existe, primero se debe pensar cómo debe ser el API de este (se debe diseñar antes de implementar) 12
13. Escribir la Especificación del Requisito (2) Se debe imaginar cómo sería el código del SUT si ya estuviera implementado y como se comprobaría que hace lo que debe hacer. Tratamos de diseñar lo que sea más cómodo y más claro, siempre que cumpla con el requisito para el cual es creado. 13
14. Implementar el Código que haga que la Prueba Pase Teniendo la prueba escrita, se codifica lo mínimo (el código que menos tiempo se lleve hacer) necesario para que la prueba pase. No importa que el código parezca feo o extraño, eso se arreglará en el siguiente paso. En este paso la idea es cumplir con el requerimiento, pero no se trata de hacerlo sin pensarlo, sino concentrarse en ser eficientes. 14
15. Refactorizar Las pruebas que se han creado, hacen que confiemos en el código escrito. Esto permite hacer modificaciones profundas del código, pues sabemos que si logramos hacer pasar todas las pruebas, seguiremos teniendo un código que cumple con los requerimientos, pero que es de más calidad que el que teníamos anteriormente. A esto se le conoce como refactorizar. 15
16. Refactorizar (2) En este paso se revisa el código (tanto el del SUT como el de la prueba) en busca de líneas duplicadas, y se eliminan mediante refactorización. Además se revisa que el código cumpla con algunos principios de diseño. 16
17. Si no se Refactoriza, no es TDD Es común entrar en una dinámica de escribir la prueba, luego el SUT, y así sucesivamente olvidando la refactorización. Si no se realiza alguna de las etapas de TDD, no se está haciendo TDD, sino otra cosa. 17
18. Pasos de TDD 18 repetir (re)escribir una prueba La prueba pasa OK Verificar si falla la prueba Escribir código productivo Hay fallos La prueba falla Ejecutar todas las pruebas Limpiar el código (refactorizar) La pruebas pasan OK
19. Integración Continua Tener un único repositorio de pruebas facilita complementar TDD con otra práctica recomendada por los procesos ágiles de desarrollo: la “integración continua”. Integrar frecuentemente nuestro trabajo con el resto del equipo de desarrollo permite ejecutar toda una batería de pruebas y así descubrir si nuestra última versión es compatible con el resto del sistema. 19
20. Las 3 Reglas de TDD de Robert “Uncle Bob” Martin No se puede escribir código productivo, a menos que sea para hacer pasar una prueba fallida. No se puede escribir más código en una prueba unitaria que lo necesario para que la prueba falle; los errores de compilación se consideran fallos. No se puede escribir más código productivo del estrictamente necesario para hacer pasar una prueba. 20
21. Las 2 Reglas de TDD de Kent Beck Se debe escribir nuevo código de negocio solo cuando falla una prueba automatizada Se debe eliminar cualquier código duplicado que se encuentre 21
22. Las 2 Reglas de TDD de Kent Beck (2) Diseñamos orgánicamente, con el código ejecutable proporcionando retroalimentación ente decisiones. Escribimos nuestras propias pruebas porque no podemos esperar 20 veces al día a que alguien más las escriba por nosotros. 22
23. Las 2 Reglas de TDD de Kent Beck (3) El ambiente de desarrollo debe proporcionar respuestas rápidas a cambios pequeños (por ejemplo, se necesita una computadora rápida y una suite de pruebas de regresión). Nuestros diseños deben consistir de componentes altamente cohesivos y débilmente acoplados, para hacer que las pruebas sean más fáciles (esto también hace que la evolución y el mantenimiento del sistema sea más fácil). 23
24. No Probar por Probar Cada vez que se va a escribir una prueba, se debe estar seguro de por qué se escribe y de qué se está probando. Es importante tener en claro qué se quiere afirmar con cada prueba, y por qué se hace de esa manera. Podría ser que el hecho de que el no poder determinar qué tipo de prueba se va a programar, indica que no se está seguro de por qué se escribe. 24
25. Tipos de Pruebas Una suposición de TDD es que estamos usando un framework de pruebas. Además de esto, existen distintos tipos de pruebas que podemos usar a la hora de desarrollar usando TDD. No existen reglas universales para escribir todos y cada uno de los tipos posibles de pruebas, ni sus posibles combinaciones. Es una cuestión que llega a ser artesanal. 25
26. Tipos de Pruebas por Potestad 26 Desarrollador Cliente Pruebas Unitarias Pruebas de Aceptación Pruebas Funcionales Pruebas de Integración Pruebas de Sistema
27.
28.
29. Pruebas de Sistema Es la más grande de las pruebas de integración, ya que integra varias partes del sistema. Se trata de una prueba que puede ir, incluso, de extremo a extremo de la aplicación o el sistema. Una prueba de sistema se realiza tal y como lo haría un usuario humano, usando los mismos puntos de entrada y llegando a modificar la base de datos, o lo que haya del otro extremo. 29
31. Atómicas Se prueba la mínima cantidad de funcionalidad posible. Esto es, probará un solo comportamiento, de un método, de una clase. El mismo método puede presentar distintas repuestas ante distintas entradas o distintos contextos; la prueba unitaria se encargará exclusivamente de uno de esos comportamientos, es decir, un único camino de ejecución 31
32. Independiente Una prueba no puede depender de otras para producir un resultado satisfactorio. No puede ser parte de una secuencia de pruebas que se deba ejecutar en un orden determinado. Debe funcionar siempre igual, independientemente de que se ejecuten otras pruebas o no. 32
33. Inocua No debe alterar el estado del sistema. Al ejecutarlo una vez, produce exactamente el mismo resultado que al ejecutarlo 20 veces. No altera la base de datos, ni envía emails, ni crea archivos ni los borra. Es como si no se hubiera ejecutado. 33
34. Rápida Esto es debido a que se ejecutan un gran número de pruebas cada pocos minutos, y tener que esperar unos cuantos segundos de manera frecuente, resulta muy improductivo. Una sola prueba debe ejecutarse en una fracción de segundo. 34
35. Cualidades de las Buenas Pruebas F.I.R.S.T Fast. Muchos cientos o miles por segundo. Isolated. Las razones de las fallas se vuelven obvias. Repeatable. Se pueden ejecutar repetidamente en cualquier orden, en cualquier momento Self-validating. No se requiere una evaluación manual. Timely. Escrito antes del código. 35
36. Fast (Rápida) Las pruebas deben ejecutarse rápidamente. Una prueba que toma un segundo o más no es una prueba rápida. Una prueba que toma medio segundo o un cuarto de segundo no es una prueba rápida. Si la prueba en si es rápida, pero la configuración de la misma y la ejecución de ambas toma más de un octavo de segundo, o un cuarto de segundo, o más, no se tiene una prueba rápida. 36
37. Isolated (Aislada) La prueba unitaria debe ser lo suficientemente pequeña, que si hay un bug, el motivo del mismo sea obvio con solo ver la prueba. Una prueba unitaria se encarga de un solo aspecto de un método. Las pruebas unitarias nunca deben depender del orden en el que se ejecutan. Establecen su estado inicial sin ayuda de otras pruebas, y limpian después de su ejecución. 37
38. Repeatable (Repetible) Deben ser capaces de ejecutarse repetidamente sin intervención. No deben depender de ningún estado inicial asumido, no deben dejar residuos que les impidan ser re-ejecutadas. Las pruebas repetibles no deben depender de servicios externos o recursos que puedan no estar siempre disponibles. 38
39. Self-validating (auto validadas) Las pruebas solo pueden o pasar o fallar, y ellas mismas deben determinar si pasan o fallan. Nadie debe examinar el resultado para determinar si son válidos o razonables 39
40. Timely (Oportunas) Las pruebas se escriben en el momento adecuado, inmediatamente antes de del código que hace que la prueba pase. 40
41. Pruebas de Integración Las pruebas de integración son la pieza que falta para cubrir el hueco entre las pruebas de unitarias y de sistema. Ayudan a unir distintas partes del sistema. Una prueba de integración puede leer y escribir de la base de datos para comprobar que, efectivamente, la lógica del negocio funciona con datos reales 41