2. Objetivos
• Estudiar paso a paso
cómo resolver la kata
Tenis con TDD y Python
• Exponer errores y ver la
manera de detectarlos.
• Comparar distintas
soluciones
desarrolladas con TDD.
Objetivos
2
3. Índice
1. Repaso de TDD
2. Kata Tennis.
3. PowerPoint-Driven
Development.
4. Primer diseño (y pruebas).
5. Continuamos.
6. Refactorizar la clase Player.
7. El Partido de Tenis.
8. Random tennis
9. Conclusiones.
Índice 10. Otras soluciones.
11. Extra 3
6. 2. El Proceso TDD
Escribimos un test que ponga de relieve funcionalidad
que queremos implementar
Si la prueba no falla estudiamos qué está sucediendo y
elegimos otra.
Escribimos el código mínimo (más corto) para que la
prueba pase con éxito. No nos preocupamos de
escribirlo bonito, tenemos libertad para tomar atajos
7. 2. El Proceso TDD
Ejecutamos la prueba y cambiamos el código hasta
que la prueba funciona.
Quitamos los atajos y refactorizamos el código y las
pruebas.
Y cómo
Triangulando, completando el conjunto de
continuamos?
pruebas o eligiendo una nueva funcionalidad.
9. Cata - Tenis
Reglas
• un jugador comienza con puntación 0.
• Los puntos se ganan en esta secuencia: 0 -> 15 -> 30 -
> 40.
• Si un jugador consigue 40 y puntúa de nuevo, el
jugador gana el juego si el otro no tiene 40 puntos.
• Si los dos jugadores tienen al mismo tiempo 40
puntos, se llama "iguales" (deuce en inglés)
• Puntuar durante iguales, da al jugador "ventaja". Si el
otro jugador puntúa en ese momento, la puntuación
vuelve a iguales.
• Si un jugador tiene "ventaja" y puntúa de nuevo, el
jugador gana el juego.
http://www.solveet.com/exercises/Kata-Tennis/13 9
10. Cata - Tenis
Metas:
• Los jugadores deben poder
ganar puntos.
• El juego debe terminar con
un ganador.
• Debes de manejar la
casuística de "iguales"
• Después de terminar el
juego, debe determinarse
quién es el ganador.
• Debe ser posible obtener la
puntuación de cualquier de
los jugadores en cualquier
momento del partido.
10
12. La primera prueba
No intentes hacerlo todo de
golpe.
• Elige algo pequeño y
simple.
• Escribe una prueba que lo
muestre.
• Codifica la prueba.
• Por ejemplo: pasar de 0 a
15 o el match aún no ha
terminado
12
13. La Segunda Prueba
¿…y ahora?
• ¿Cuál es la prueba que te
hace avanzar más?
• Por ejemplo puedes
continuar con las
puntuaciones hasta la
casuística de los 40.
• Recuerda refactorizar.
13
14. Ha pasado el tiempo
¿atascado?
• No te preocupes si tienes
que volver a empezar.
• No es una pérdida de
tiempo. Ya verás como la
siguiente vez te sale
MUCHO MEJOR.
14
15. Esto se acaba
¿Has terminado?
• ¿Y si intentas simular una
partida de tenis con
números aleatorios?.
¿No has terminado?
• Refactoriza y que quede
bonito
15
17. Primeros pasos
Metas:
• Los jugadores deben poder
ganar puntos.
Tenemos que empezar por
• El juego debe terminar con algo. ¿Por dónde?
un ganador.
• Debes de manejar la
casuística de "iguales"
• Después de terminar el
juego, debe determinarse
quién es el ganador. Mover
• Debe ser posible obtener la
puntuación de cualquier de
los jugadores en cualquier
momento del partido.
17
18. Primeros pasos
Ejemplos prácticos (candidatos a casos de prueba)
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
8 casos de prueba posibles
18
19. Primeros pasos
Manos a la obra
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
8 casos de prueba posibles
19
20. Primeros pasos
¿Cómo será nuestra prueba?
1 • ¿Cómo creamos un
jugador?
2
• No hay nada que hacer
3 • ¿Cómo conocemos la
puntuación de un
jugador?
• ¿Cómo se expresa la
Con nuestra primera prueba vamos a puntuación del jugador
empezar a contestar a estas preguntas y, así,
veremos si elegimos una buena alternativa o
no
21. Primeros Pasos
También hemos tomado muchas decisiones de diseño.
He decidido crear un módulo Tennis que contiene una clase Player
He decidido utilizar un constructor sin parámetros
He decidido añadir un método sin parámetros para saber la puntuación de ese
jugador
He decidido que la puntuación sea una cadena de texto
23. Primeros Pasos
Para cambiar esto necesitaré más
adelante una prueba que me haga
cambiarlo. A por ello.
Nada que refactorizar: ni código ni pruebas.
24. Primeros pasos
Ejemplos prácticos (candidatos a casos de prueba)
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
24
25. Primeros Pasos
Después
Antes
Triangulación.
Podríamos refactorizar algunos detalles.
26. Primeros Pasos
Ya tenemos nuestras primeras pruebas
listas y nuestro código crece…. Pero,
¿qué estamos haciendo?
• Estamos diseñando cómo implementamos la puntuación de
un jugador.
• Estamos diseñando cómos otras partes del código indicarán
que un jugador ha puntuado.
• Estamos entrando en foco más en diseñar el código qué nos
es útil que en implementar el problema.
28. Pruebas de anotación
Ejemplos prácticos (candidatos a casos de prueba)
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
28
30. Pruebas de anotación
Mal olor: demasiado código repetido, diseño difícil de probar.
Esta refactorización nos pone de relieve otro problema…
que ignoramos
31. Pruebas de anotación
Ejemplos prácticos (candidatos a casos de prueba)
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
Parece que vamos avanzando.
31
33. Anotando con el segundo jugador
Necesitamos al segundo jugador.
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
33
34. Anotando con el segundo jugador
Las pruebas anteriores ya no se ejecutan porque
no les pasaba un jugador (ni los necesitaban).
Hay que arreglarlo ?
35. Anotando con el segundo jugador
No ha sido una buena prueba, no he introducido nada que
necesitara ni que haya hecho crecer mi código.
36. Anotando con el segundo jugador
Necesitamos al segundo jugador.
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Mover derecha 15 puntos 30 puntos
Mover derecha 30 puntos 40 puntos
Mover derecha 40 puntos y el otro jugador no tiene 40 puntos Gana
Mover derecha 40 puntos y el otro jugador tiene 40 puntos Ventaja
Mover derecha 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Mover derecha Ventaja Gana
Hace evolucionar mi sistema.
36
37. Anotando con el segundo jugador
Las pruebas anteriores ya no se ejecutan porque a
veces el segundo jugador es “None”. Hay que
arreglarlo.
38. Anotando con el segundo jugador
Un apaño (añadir a un segundo jugador como parámetro y hacerlo
None para que mis pruebas anteriores ejecuten) olor me lleva a
otro mal olor (ver si tengo un segundo jugador o no).
Mejor simplificar y que todas las pruebas trabajen con un segundo
jugador refactorizar.
39. Anotando con el segundo jugador
Necesitamos al segundo jugador.
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
Esta es la última prueba clave.
39
41. Anotando con el segundo jugador
La última prueba.
Acción Estado Resultado
-- El jugador no ha anotado ningún tanto 0 puntos
Jugador anota un tanto Sin puntos 15 puntos
Jugador anota un tanto 15 puntos 30 puntos
Jugador anota un tanto 30 puntos 40 puntos
Jugador anota un tanto 40 puntos y el otro jugador no tiene 40 puntos Gana
Jugador anota un tanto 40 puntos y el otro jugador tiene 40 puntos Ventaja
Jugador anota un tanto 40 puntos y el otro jugador tiene ventaja Se queda como está y el otro
jugador vuelve a 40 puntos
Jugador anota un tanto Ventaja Gana
Esta prueba no sería necesaria. Como vamos a ver
41
43. Conclusiones
Hemos terminado pero…..
• Las pruebas son difíciles de entender.
• He escrito código sólo para las pruebas.
• He decidido cómo representar las
puntuaciones (cadenas).
Arreglémoslo.
48. Refactorizando Player
Adiós a los malos olores.
• Ahora as pruebas hablan la lógica
del negocio y utilizan sus
conceptos, en vez de trabajar con
valores numéricos y cadenas.
• Lo que más puede cambiar está
solo en un sitio.
• Tapo el apaño del constructor (a
la espera de mocks).
50. El Partido de Tennis
Metas:
• Los jugadores deben poder Método winPoint
ganar puntos.
• El juego debe terminar con
un ganador.
• Debes de manejar la Método winPoint
casuística de "iguales"
• Después de terminar el
juego, debe determinarse
quién es el ganador.
• Debe ser posible obtener la
puntuación de cualquier de Método getScore
los jugadores en cualquier
momento del partido.
50
51. El Partido de Tennis
Ejemplos prácticos (candidatos a casos de prueba)
Acción Estado Resultado
Jugador anota un tanto Dos jugadores, ningún ganador El juego continúa
Jugador anota un tanto Dos jugadores, un único ganador El juego termina. Se indica el
ganador
2 casos de prueba posibles (de
entrada).
Estos ejemplos de prueba no son completos. No hay que preocuparse, ya
descubriremos qué falla más adelante
51
52. El Partido de Tenis
• Crear la clase match
• Darle un método
playMatch
• Hacer que el método anote
al jugador A
53. El Partido de Tenis
Podemos refactorizar el caso de prueba.
Aprovechar lo que ya tenemos
del otro conjunto de pruebas
No exponer detalles de la
interfaz. Actuar, no pedir
información
54. El Partido de Tenis
Hemos refactorizado el código en desarrollo y las
pruebas.
55. El Partido de Tenis
Ejemplos prácticos (candidatos a casos de prueba)
Acción Estado Resultado
Jugador anota un tanto Dos jugadores, ningún ganador El juego continúa
Jugador anota un tanto Dos jugadores, un único ganador El juego termina. Se indica el
ganador
¿Estamos a una prueba de acabar el
desarrollo? Comprobémoslo
55
57. El Partido de Tenis
Ejemplos prácticos (candidatos a casos de prueba)
Acción Estado Resultado
Jugador anota un tanto Dos jugadores, ningún ganador El juego continúa
Jugador anota un tanto Dos jugadores, un único ganador El juego termina. Se indica el
ganador
Aquí falta algo
¿Qué ha pasado?
57
58. El Partido de Tenis
• Hay un valor de prueba que no estamos tratando.
• ¿Cómo podemos hace que anote el otro jugador?
• ¿Cómo podemos tener una prueba que siempre
puntúe B y sea ganador¿ ¿y otra en la que puntué
primero A y después B?
• En verdad lo que queremos decir es….
• ¿Cómo podemos cambiar lo que pasa dentro del while
en el método playmatch sin montar un follón?
• ¿Hemos hecho un mal diseño y tenemos que
retroceder?
• Veámoslo.
59. El partido de Tennis
¿Cómo podeos hacer que, en algunas
pruebas puntúe el jugador A y en otras
puntúe el jugador B?
Evitamos la sobre ingeniería y buscamos la
solución más sencilla que se nos ocurra
60. El Partido de Tennis
Vamos a reescribir las prueba para poder introducir los
valores de prueba (en este caso el jugador que anota.
Nada de momento.
61. El Partido de Tenis
Que gane el jugador B.
Bucle infinito
Ok
62. El Partido de Tenis
Hemos terminado pero…..
• Hemos hecho un apaño que nos
convence poco.
• ¿Estamos seguros de que funciona?
• ¿Podríamos modificarlo fácilmente?
• ¿Es fácil de entender?
Arreglémoslo.
64. El Partido de Tenis
Metas:
• Los jugadores deben poder Método winPoint
ganar puntos.
• El juego debe terminar con Método winPoint
un ganador.
• Debes de manejar la Método winPoint
casuística de "iguales"
• Después de terminar el
juego, debe determinarse Método winPoint
quién es el ganador.
• Debe ser posible obtener la
puntuación de cualquier de Método getScore
los jugadores en cualquier
momento del partido.
64
66. Random Tenis
• ¿Y si se calcula aleatoriamente el jugador que anota?
• ¿Y si ejecuto muchos partidos seguidos y compruebo
que todo funciona correctamente?
• Esto ya no son pruebas unitarias.
• Si podemos hacerlo sin cambiar una coma de nuestro
código es una buena indicación.
• Si tenemos que cambiar algo, lo estamos mejorando.
Vamos a hacerlo
68. Random Tenis
Esto no es código de
producción ,sino de
pruebas
Todo funciona a la primera
¿Por qué limitarnos a un único partido? ¿Por qué no
jugamos 10.000? Vamos a hacerlo
69. Random Tenis
10.000 partidos……
Este test no debería de fallar si todo lo hicimos
bien (y el test está bien escrito)
70. Random Tenis
Ooops, demasiado lento. No vale
para prueba unitaria.
Pues parece que funciona.
72. Conclusiones
• Después de 10.000 partidas no hemos detectado
ningún error.
• ¿Podemos decir que el software funciona?
• Nunca.
• Solo estamos buscando unos errores concretos,
puede tener otros que no estemos buscando.
• Los 10.000 partidas se basan en algo que no está
probado.
• Si RandomScore tiene fallos, las pruebas pueden
dar falsos positivos
73. Conclusiones
• Notas:
– No está contemplado que se siga puntuando
después de que un jugador gane (no lo pone en
los requisitos pero podemos hacerlo si lo
consideramos adecuado).
75. Otras soluciones
TDD in Python in 5 minutes
Set
Score
TestSetWinning: 6 pruebas
TestScoreNames: 1 prueba
http://css.dzone.com/articles/tdd-python-5-minutes
84. Actividades
• Consulta las soluciones
si pruebas
• ¿Crees que habrían
salido estas soluciones
haciendo TDD?
• ¿Serías capa de escribir
pruebas para ese código
tal cuál está escrito, sin
modificarlo?
Autoevalua TDD
84
87. Extra
Ejemplo de mocks en Python
http://iwt2-
javierj.tumblr.com/post/36695988608/mocks-en-python-
previa-python-tdd
Ejemplo de Behave en Python
http://iwt2-javierj.tumblr.com/post/36762766836/atdd-
bdd-con-python-y-behave-previa-python-tdd
87