1. agile software development & services
Cómo escribir buenos test
al hacer TDD
www.10pines.com
Hernán Wilkinson
Twitter: @HernanWilkinson
Blog: objectmodels.blogspot.com
www.10pines.com
2. ¿Qué es TDD?
Técnica de Aprendizaje
Iterativa e Incremental
Basada en Feedback Inmediato
Como side-effect:
Recuerda todo lo aprendido
Y permite asegurarnos de no haber
“desaprendido”
Incluye análisis, diseño, programación
y testing
3. ¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
4. ¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
2) Correr todos los tests
- Implementar la solución más simple que
haga pasar el/los test/s
- GOTO 2 hasta que “todos los tests” pasen
5. ¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
2) Correr todos los tests
- Implementar la solución más simple que
haga pasar el/los test/s
- GOTO 2 hasta que “todos los tests” pasen
3) Reflexiono - ¿Se puede mejorar el código?
- Sí -> Refactorizar. GOTO 2
- No -> GOTO 1
6. ¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
2) Correr todos los tests
- Implementar la solución más simple que
haga pasar el/los test/s
- GOTO 2 hasta que “todos los tests” pasen
3) Reflexiono - ¿Se puede mejorar el código?
- Sí -> Refactorizar. GOTO 2
- No -> GOTO 1
7. ¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
2) Correr todos los tests
- Implementar la solución más simple que
haga pasar el/los test/s
- GOTO 2 hasta que “todos los tests” pasen
3) Reflexiono - ¿Se puede mejorar el código?
- Sí -> Refactorizar. GOTO 2
- No -> GOTO 1
8. Regla 1: Si el test no
falla la primera vez que
corre es porque:
a) Estamos testeando algo
testeado
b) Nos adelantamos en el
paso 2
9. ¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
2) Correr todos los tests
- Implementar la solución más simple que
haga pasar el/los test/s
- GOTO 2 hasta que “todos los tests” pasen
3) Reflexiono - ¿Se puede mejorar el código?
- Sí -> Refactorizar. GOTO 2
- No -> GOTO 1
10. ¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
2) Correr todos los tests
- Implementar la solución más simple que
haga pasar el/los test/s
- GOTO 2 hasta que “todos los tests” pasen
3) Reflexiono - ¿Se puede mejorar el código?
- Sí -> Refactorizar. GOTO 2
- No -> GOTO 1
12. Tiempo
Si nos lleva mucho tiempo escribir el
test
El test no es el más sencillo
¿Nos cuesta mucho crear los objetos
para la prueba?
Hay que crear objetos que ayuden en la
creación de objetos
El diseño del sistema no es bueno y
nos dificulta la escritura del test
13. Tiempo
Si nos lleva mucho tiempo hacer pasar
el test
El test no era el más sencillo Borrar el
test e intentar con uno más sencillo
La implementación no resuelve el
problema ¡Debuggear!
El diseño del sistema no es bueno y
nos dificulta la implementación de
nueva funcionalidad Hacer paso 3
para mejorar el diseño antes de
seguir
14. Tiempo
Los test tardan mucho tiempo en
ejecutar
El sistema está acoplado con recursos
externos que hace que ejecute “lento”.
Ejemplo: Base de datos
Los test no verifican funcionalidad sino
performance
Test de performance se hacen con
testing, no TDD
15. Tiempo
Tardo mucho en hacer refactorings
¡Aprender refactorings automatizados!
Si están programando con editores de
texto ¡pasar a un IDE!
Aprender como hacer cambios chicos por
medio de refactorings encadenados
El diseño del sistema es muy malo, esta
muy acoplado y no queda otra que tomarse
tiempo para arreglarlo
16. Estructura de los tests
Setup
Exercise
Assert
Establece el contexto inicial para la
ejecución del test. Pre-condición del test
(puede ser reificado en mensaje setUp)
Ejercita la funcionalidad específica que se
está testeando. Determina QUÉ se está
testeando.
Verifica que los resultados sean los
esperados. Post-condición del test
17. Ejemplo
▶ Algoritmo para calcular los factores primos de un
número entero. Debe devolver una lista con ellos
– 1 -> {} (no tiene factores primos)
– 2 -> { 2 }
– 3 -> { 3 }
– 4 -> { 2,2 }
– 5 -> { 5 }
– 6 -> { 2,3 }
– 7 -> { 7 }
– 8 -> { 2,2,2 }
– 9 -> { 3,3 }
– 10 -> { 2,5 }
– Etc
34. Regla 4: Nombrar los
tests en base al caso
funcional y no en base
a los datos de prueba
35. Tip: Dato de Prueba != Caso de Prueba
Dato de Prueba: Ejemplos concretos que
“definen” un caso de prueba
Caso de Prueba: Generalización que
incluye los datos de prueba
39. Ejemplo
▶ Modelar un Calendario de días feriados al que se le pueda
preguntar si una fecha es feriado o no
▶ Se pueda indicar qué días son feriados de la siguiente
manera:
– Por medio de un día de la semana, ej. Domingo
– Por medio de un día de un mes, ej. 25 de Diciembre
– Por medio de un día particular, ej. 20/4/2012
55. Regla 7: Las aserciones
sobre colecciones no deben
acoplar a la implementación
Regla 8: Las aserciones
sobre colecciones deben
asegurar la doble inclusión
Tip: asertar size e inclusión de cada
objeto
58. Regla 9: Los tests son
un sistema más que
hay que desarrollar y
mantener. Hacerlo
usando las mismas
reglas de diseño que el
sistema principal
59. Regla 10: Los tests son un
sistema que usa el sistema
principal, por lo tanto los
tests nos convierten en los
primeros usuarios del
sistema principal y nos
hacen sufrir sus problemas
67. ¡Ahora va a funcionar siempre, no
importa que día sea hoy!
68. Regla 11: Cuando hay
dependencia entre datos de
prueba e implementación,
romper el acoplamiento
parametrizando
Tip: siempre usar datos de
prueba relativos, no absolutos
69. Regla 12: Nunca acoplar la
implementación con fuentes
de información ni sistemas
externos, parametrizar
70. Acceso via interface REST El carrito pasa a ser
inválido (inutilizable) luego de 30 minutos de no usarlo
71.
72. ¿Qué principio de diseño se está
violando? ¿Cómo lo evito? ¿Qué
tiene que controlar el test?
77. Regla 13: El test tiene
que estar en control de
TODO
(hasta del paso del tiempo si es
necesario)
Tip: Si hay que controlar el tiempo,
simular el reloj
80. Solo la colaboración que
levanta la excepción
Aserto que se levantó la ex. esperada
81. Solo la colaboración que
levanta la excepción
Aserto que se levantó la ex. esperada
Aserto sobre la post-condición
82. Regla 14: Cuando se
testea por excepciones
se debe:
1) Una colaboración en el try
2) Asertar exc. correcta
3) Asertar post-condición
Tip: falta de aserción sobre post-condición
puede indicar que no estamos modelando
algo
95. Regla 16: Modelar los
ambientes de
ejecución y dejarlos
como único punto de
acceso a toda la
información
96. ▶ Regla 1: Si el test no falla la primera vez es
porque …
▶ Regla 2: Sensar el tiempo que nos lleva
realizar cada paso
▶ Regla 3: Nombrar los tests sintetizando el
setup, exercise y assertions en una frase
▶ Regla 4: Nombrar los tests en base al caso
funcional y no en base a los datos de prueba
Conclusiones
97. ▶ Regla 5: ¡Los tests no son una verificación
formal!
▶ Regla 6: Los tests deben seguir la estructura
setup-exercise-assertion
▶ Regla 7: Las aserciones sobre colecciones no
deben acoplar a la implementación
▶ Regla 8: Las aserciones sobre colecciones
deben asegurar la doble inclusión
Conclusiones
98. ▶ Regla 9: Los tests son un sistema más que hay
que desarrollar y mantener …
▶ Regla 10: … los tests nos convierten en los
primeros usuarios del sistema …
▶ Regla 11: … romper el acoplamiento
parametrizando
▶ Regla 12: Nunca acoplar la implementación
con fuentes de información ni sistemas
externos, parametrizar
Conclusiones
99. ▶ Regla 13: El test tiene que estar en control de
TODO
▶ Regla 14: Cuando se testea por excepciones se
debe …
▶ Regla 15: Modelar los conjuntos de objetos
(sistemas)
▶ Regla 16: Modelar los ambientes de ejecución
y dejarlos como único punto de acceso a toda
la información
Conclusiones
100.
101. agile software development & services
Muchas gracias!
info@10pines.com
www.10Pines.com
twitter: @10Pines
Argentina
Tel.: +54 (11) 6091-3125
Av. Alem 693, 5B
(1001) Buenos Aires