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
¿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
¿Cómo se hace TDD?
1) Escribir un test
- Debe ser el más sencillo que se nos ocurra
- Debe fallar al correrlo
¿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
¿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
¿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
¿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
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
¿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
¿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
Regla 2: Sensar el
tiempo que nos lleva
realizar cada paso
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
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
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
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 
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
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
¿Cómo lo llamamos?
¿Qué tal así?
¿Entonces cómo llamamos
este?
Regla 3: Nombrar los
tests sintetizando el
setup, exercise y
assertions en una frase
Tip: Nombrar los tests cuando
hayamos avanzado en la solución
¿Cuál es el setup y exercise?
Setup
Exercise
Assert
¿Qué tal este?
No suena muy bien…
¿Cómo llamamos estos tests?
 Nombres casi iguales…
 “Nombres repetidos”
 ¡Tests del mismo caso!
¡Mismo caso funcional!
Regla 4: Nombrar los
tests en base al caso
funcional y no en base
a los datos de prueba
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
¡Me da miedo!
¿Qué pasa si …?
 Decisión complicada…
 Números primos infinitos…
 Ver la implementación
lamentablemente
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
¿Cómo lo llamamos?
 ¿Si hago un test con 3 días
pasará?
 ¿y con 4 …?
 ¿y con 7?
¡Inducción Incorrecta!
Regla 5: ¡Los tests no
son una verificación
formal!
Técnica: Testar con datos testigos
Técnica: Testar con datos bordes
¿Aserción luego del set
up?
¿Aserción luego del set
up?
Para pensar… first ?
 Separar el test en 2
¿Exercise luego de
aserción?
¿Exercise luego de
aserción?
Para pensar… first ? second?
 Separar el test en 2
Regla 6: Los tests
deben seguir la
estructura setup-
exercise-assertion
first ? second?
Pensar en “tipo” no en
implementación
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
Aserción repetidaAserción repetida
¡Reificar aserciones!
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
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
¿Va a funcionar siempre?
¿Qué problema de diseño tiene
esta implementación?
¡Saco acoplamiento
parametrizando la fecha!
¡Ahora la fecha de prueba es
relativa, no absoluta!
¡Ahora va a funcionar siempre, no
importa que día sea hoy!
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
Regla 12: Nunca acoplar la
implementación con fuentes
de información ni sistemas
externos, parametrizar
Acceso via interface REST  El carrito pasa a ser
inválido (inutilizable) luego de 30 minutos de no usarlo
¿Qué principio de diseño se está
violando? ¿Cómo lo evito? ¿Qué
tiene que controlar el test?
Reloj manual para controlar
el paso del tiempo
Parametrizo cómo obtiene
la hora
Reloj manual para controlar
el paso del tiempo
Parametrizo cómo obtiene
la hora
Reloj manual para controlar
el paso del tiempo
Simulo paso del tiempo
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
¿Cómo hay que testear
excepciones?
Solo la colaboración que
levanta la excepción
Solo la colaboración que
levanta la excepción
Aserto que se levantó la ex. esperada
Solo la colaboración que
levanta la excepción
Aserto que se levantó la ex. esperada
Aserto sobre la post-condición
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
Referencia directa a la base de datos
Referencia directa a la base de datos y cómo
se busca en ella
¿Cómo rompo este acoplamiento?
Modela un sub-sistema
Lo implementa de manera persistente
Lo implementa de manera transient
Regla 15: Modelar los
conjuntos de objetos
(sistemas)
Tip: Queda representada la arquitectura
del sistema por medio de objetos
¿Cómo defino que subsistema
usar?
Regla 16: Modelar los
ambientes de
ejecución y dejarlos
como único punto de
acceso a toda la
información
▶ 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
▶ 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
▶ 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
▶ 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
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

Como escribir buenos tests al hacer TDD

  • 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écnicade 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 haceTDD? 1) Escribir un test - Debe ser el más sencillo que se nos ocurra - Debe fallar al correrlo
  • 4.
    ¿Cómo se haceTDD? 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 haceTDD? 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 haceTDD? 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 haceTDD? 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: Siel 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 haceTDD? 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 haceTDD? 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
  • 11.
    Regla 2: Sensarel tiempo que nos lleva realizar cada paso
  • 12.
    Tiempo Si nos llevamucho 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 llevamucho 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 tardanmucho 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 enhacer 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 lostests 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 paracalcular 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
  • 18.
  • 19.
  • 20.
  • 21.
    Regla 3: Nombrarlos tests sintetizando el setup, exercise y assertions en una frase Tip: Nombrar los tests cuando hayamos avanzado en la solución
  • 22.
    ¿Cuál es elsetup y exercise?
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
    No suena muybien…
  • 30.
  • 32.
     Nombres casiiguales…  “Nombres repetidos”  ¡Tests del mismo caso!
  • 33.
  • 34.
    Regla 4: Nombrarlos tests en base al caso funcional y no en base a los datos de prueba
  • 35.
    Tip: Dato dePrueba != 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
  • 36.
  • 38.
     Decisión complicada… Números primos infinitos…  Ver la implementación lamentablemente
  • 39.
    Ejemplo ▶ Modelar unCalendario 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
  • 40.
  • 43.
     ¿Si hagoun test con 3 días pasará?  ¿y con 4 …?  ¿y con 7?
  • 44.
  • 45.
    Regla 5: ¡Lostests no son una verificación formal! Técnica: Testar con datos testigos Técnica: Testar con datos bordes
  • 46.
  • 47.
    ¿Aserción luego delset up? Para pensar… first ?
  • 48.
     Separar eltest en 2
  • 49.
  • 50.
    ¿Exercise luego de aserción? Parapensar… first ? second?
  • 51.
     Separar eltest en 2
  • 52.
    Regla 6: Lostests deben seguir la estructura setup- exercise-assertion
  • 53.
  • 54.
    Pensar en “tipo”no en implementación
  • 55.
    Regla 7: Lasaserciones 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
  • 56.
  • 57.
  • 58.
    Regla 9: Lostests 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: Lostests 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
  • 63.
  • 64.
    ¿Qué problema dediseño tiene esta implementación?
  • 65.
  • 66.
    ¡Ahora la fechade prueba es relativa, no absoluta!
  • 67.
    ¡Ahora va afuncionar siempre, no importa que día sea hoy!
  • 68.
    Regla 11: Cuandohay dependencia entre datos de prueba e implementación, romper el acoplamiento parametrizando Tip: siempre usar datos de prueba relativos, no absolutos
  • 69.
    Regla 12: Nuncaacoplar la implementación con fuentes de información ni sistemas externos, parametrizar
  • 70.
    Acceso via interfaceREST  El carrito pasa a ser inválido (inutilizable) luego de 30 minutos de no usarlo
  • 72.
    ¿Qué principio dediseño se está violando? ¿Cómo lo evito? ¿Qué tiene que controlar el test?
  • 74.
    Reloj manual paracontrolar el paso del tiempo
  • 75.
    Parametrizo cómo obtiene lahora Reloj manual para controlar el paso del tiempo
  • 76.
    Parametrizo cómo obtiene lahora Reloj manual para controlar el paso del tiempo Simulo paso del tiempo
  • 77.
    Regla 13: Eltest 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
  • 78.
    ¿Cómo hay quetestear excepciones?
  • 79.
    Solo la colaboraciónque levanta la excepción
  • 80.
    Solo la colaboraciónque levanta la excepción Aserto que se levantó la ex. esperada
  • 81.
    Solo la colaboraciónque levanta la excepción Aserto que se levantó la ex. esperada Aserto sobre la post-condición
  • 82.
    Regla 14: Cuandose 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
  • 84.
    Referencia directa ala base de datos
  • 85.
    Referencia directa ala base de datos y cómo se busca en ella ¿Cómo rompo este acoplamiento?
  • 86.
  • 87.
    Lo implementa demanera persistente
  • 88.
    Lo implementa demanera transient
  • 89.
    Regla 15: Modelarlos conjuntos de objetos (sistemas) Tip: Queda representada la arquitectura del sistema por medio de objetos
  • 90.
    ¿Cómo defino quesubsistema usar?
  • 95.
    Regla 16: Modelarlos 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
  • 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