El documento describe el desarrollo guiado por pruebas (TDD), incluyendo que se trata de una técnica de diseño e implementación de software basada en derivar código de pruebas antes del código de producción. Explica las reglas, ciclo y ventajas de TDD, y provee un ejemplo de su aplicación al desarrollar una función para calcular factores primos de un número.
2. Universidad de Oriente
Departamento de Ingeniería de Sistemas
Cursos Especiales de Grado
Área: Ciencias de la Computación
Lenguajes y Técnicas Avanzadas de Programación
Bachilleres:
Barreto Daniela
Charles Adriana
Equipo: Delphi
Prof. Jonathan Vásquez
3. Introducción
Desarrollo Dirigido por Test (TDD)
Las Reglas de TDD
Ciclo de desarrollo de TDD
Ventajas de usar TDD
Tips para el aprendizaje de TDD
Ejemplo
Conclusión
Bibliografía
Equipo: Delphi Daniela Barreto
4. Introducción
Test-Driven Development, surgió como practica de diseño de software
orientado a objetos, basada en derivar el código de pruebas automatizadas
escritas antes del mismo. Con el correr de los años, se ha ido ampliando su
uso. Se ha utilizado para poner el énfasis en hacer pequeñas pruebas de
unidad que garanticen la cohesión de las clases, así como en pruebas de
integración que aseguren la calidad del diseño y la separación de
incumbencias. Y el los últimos años se ha comenzado a avanzar con los
conceptos de TDD hacia las pruebas de interacción a través de interfaces de
usuario.
Equipo: Delphi Daniela Barreto
5. Según Ble Jurado, C (2010), es una técnica
de diseño e implementación de software incluida
dentro de la metodóloga XP. TDD es una técnica
para diseñar software que se centra en tres pilare
fundamentales:
La implementación de las funciones juntas que el cliente necesita y
no mas
La minimización del número de defectos que llegan al software en
fase de producción.
La producción del software modular, altamente reutilizable y
preparado para el cambio.
Equipo: Delphi
6. ¿Cómo lo
hago?
¿Por dónde
empiezo?
¿Cómo se que es
lo que hay que
implementar y lo
que no?
¿Cómo escribir un
código que se
pueda modificar si
romper
funcionalidad
existente?
Equipo: Delphi
7. No está permitido escribir ningún
código de producción sin tener una
prueba que falle
No está permitido escribir más
código de producción que el
necesario para pasar su prueba
unitaria.
No está permitido escribir más
código de prueba que el necesario
para fallar (y no compilar es fallar).
Según Martin Robert C. (2009), una de las máximas
autoridades en TDD, describe el proceso en base a tres simples
reglas:
Equipo: Delphi Daniela Barreto
8. 1. El cliente escribe su historia de
usuario.2. Se escriben junto con el cliente los
criterios de aceptación de esta
historia3. Se escoge el criterio de aceptación
más simple y se traduce en una
prueba unitaria
4. Se comprueba que esta prueba
falla.
5.Se escribe el código que hace pasar
la prueba.
6. Se ejecutan todas las pruebas
automatizadas7. Se refactoriza y se limpia el código.8.Se vuelven a pasar todas las
pruebas automatizadas para
comprobar que todo sigue
funcionando.
9. Volvemos al punto 3 con los criterios de
aceptación que falten y repetimos el ciclo
una y otra vez hasta completar nuestra
aplicación
Equipo: Delphi Daniela Barreto
9. La pregunta habitual cuando alguien te habla sobre TDD es
¿Porque es mejor hacer las pruebas antes que el código?
Para responder a esta pregunta:
Los programadores que utilizan el desarrollo guiado por
pruebas en un proyecto virgen encuentran que en raras
ocasiones tienen la necesidad de utilizar el depurador o
debugger.
A pesar de los elevados requisitos iníciales de aplicar esta
metodología, el desarrollo guiado por pruebas (TDD)
puede proporcionar un gran valor añadido en la creación
de software, produciendo aplicaciones de más calidad y en
menos tiempo.
Ofrece más que una simple validación del cumplimiento de los
requisitos, también puede guiar el diseño de un programa.
cuando es utilizada correctamente, se asegura de que todo el
código escrito está cubierto por una prueba. Esto puede dar al
programador un mayor nivel de confianza en el código
Equipo: Delphi Daniela Barreto
10. Es recomendable probar una unidad de código solo a través
de su API pública (y en términos prácticos, "protegido" es
efectivamente público). Al hacer esto, obtenemos un mejor
aislamiento de los detalles específicos de la implementación.
Evita calcular el valor esperado, ya que podríamos terminar
duplicando el código de producción, incluyendo cualquier
error que este pudiera tener. Preferiblemente, calcula el
resultado esperado manualmente (y revísalo por lo menos un
par de veces) y colócalo como una constante
Evita compartir estado entre pruebas. Debe ser posible
ejecutar las pruebas en cualquier orden o incluso, ejecutar
una prueba dentro de otra prueba. Mantener las pruebas
aisladas de las demás también es un factor indispensable para
la confiabilidad y mantenibilidad de las mismas.
Equipo: Delphi Daniela Barreto
11. Frecuentemente los errores en el código de pruebas se
esconden en los métodos de inicialización. Mantener
este código simple y compacto puede ser un gran paso
para la mantenibilidad del código.
Si no es posible determinar lo que una prueba está
haciendo, es probable que en realidad esté
verificando múltiples cosas: hazla pedazos y
convierte cada uno en su propia prueba individual.
Si una parte del código es particularmente resistente a tus
esfuerzos de probarla, voltea al código en busca de
problemas en el diseño del mismo. Un código fácil de
probar frecuentemente está débilmente acoplado con el
resto del sistema, es altamente cohesivo y sigue los
principios fundamentales del diseño de software.
Equipo: Delphi Daniela Barreto
12. Vamos a crear un código en Python que cuando le
indiquemos un número entero, nos regrese un
arreglo con sus factores primos.
from unittest import main, TestCase
class TestPrimeFactors(TestCase):
def testPrimesOf0(self):
self.assertEquals([], factorsOf(0))
if __name__ == '__main__':
main()
Al correr este código se
ejecuta la prueba
“testPrimesOf0” y
obtenemos un error
"NameError: global name
'factorsOf' is not defined".
Esta es nuestra señal para
detenernos y agregar a
nuestro código la definición
de factorsOf:
def factorsOf(n):
return []
Equipo: Delphi Daniela Barreto
13. def
testPrimesOf0to1(self):
self.assertEquals([],
factorsOf(0))
self.assertEquals([],
factorsOf(1))
Ahora ya pasa nuestra
prueba. Así que podemos
continuar escribiendo
código de prueba.
Reemplazamos nuestro
caso de prueba para incluir
el caso del 1.
def
testPrimesOf2(self):
self.assertEquals([
2], factorsOf(2))
Funciona bien. Ahora
agreguemos una prueba
para el 2, el cual es un
número primo y por lo
tanto debe regresar un
arreglo con su mismo
valor.
def factorsOf(n):
if n > 1:
return [n]
return []
Como era de
esperarse, la prueba
falla, así que es hora
de escribir código.
Cambiamos la
implementación de
nuestra función
factorsOf por:
Equipo: Delphi Daniela Barreto
15. def factorsOf(n):
result, factor = [], 2
while n > 1:
while n % factor == 0:
result.append(factor)
n /= factor
factor += 1
return result
Obtenemos un error con el
mensaje: “AssertionError: Lists
differ: [2, 2] != [4]”, ya que
nuestra función factorsOf no
está lista para arrojar el
resultado esperado. Hora de
modificar el código:
Equipo: Delphi Daniela Barreto
16. El TDD es beneficioso independientemente de la metodología que se esté
utilizando en el proyecto.
Ayuda a escribir código más modular, más cohesionado, menos acoplado y
más robusto.
Se automatiza la detección muy precoz de regresiones funcionales y de bugs,
facilitando mucho su resolución y disminuyendo significativamente su
impacto en tiempos y coste.
Los tests documentan claramente qué comportamiento se espera de cada
unidad testeada, sobre todo si en su codificación se han seguido los
principios de "código limpio”
Si realizamos primero las pruebas podremos hacer un ejercicio previo de
análisis de los diferentes requisitos necesarios para el ejercicio que se nos
plantea, esto nos ayuda a crear el código mínimamente necesario para
nuestro propósito, permitiéndonos no generar extra que luego se convierte en
basura o código muerto.
Equipo: Delphi Daniela Barreto
17. Beck K. Test-Driven Development. By Example. Pearson
Education 2003.
Ble Jurado C, “Diseño Ágil con TDD”, eBook. Primera
Edición. Enero 2010.
Osherove R. The Art of Unit Testing. Manning
Publications, 2009
Equipo: Delphi Daniela Barreto