Contenido ……………………………… 2 Introducción …………………………… 3
Un poco de Historia …………………… 4 Test Driven Development ……………… 5
Ciclo de desarrollo basado en pruebas … 6 Ventajas de Usar TDD……………………10
Ejemplo de la cuenta bancaria ………… 11 Referencia Bibliográficas…………………19
Revista digital: Test Driven Development
Revista digital: Test Driven Development
Desarrollo guiado por pruebas de software, o Test-driven development (TDD) es una práctica de ingeniería de software que involucra otras dos prácticas: Escribir las pruebas primero (Test First Development) y Refactorización (Refactoring). Para escribir las pruebas
generalmente se utilizan las pruebas unitarias (unit test en inglés). En primer lugar, se escribe una prueba y se verifica que las pruebas fallan. A continuación, se implementa el código que hace que la prueba pase satisfactoriamente y seguidamente se refactoriza el código escrito. El propósito del desarrollo guiado por pruebas es lograr un código limpio que funcione. La idea es que los requisitos sean traducidos a pruebas, de este modo, cuando las pruebas pasen se garantizará que el software
cumple con los requisitos que se han establecido. Para que funcione el desarrollo guiado por pruebas, el sistema que se programa tiene que ser lo suficientemente flexible como para permitir
que sea probado automáticamente. Cada prueba será suficientemente pequeña como para que permita determinar unívocamente si el código probado pasa o no la verificación que ésta le impone. El diseño se ve favorecido ya que se evita el indeseado "sobre diseño" de las aplicaciones y se logran interfaces más claras y un código más cohesivo. Frameworks como JUnit proveen de un mecanismo para manejar y ejecutar conjuntos de pruebas automatizadas.
Revista digital: Test Driven Development
Basado en pruebas de desarrollo (TDD) es un proceso de desarrollo de software que se basa en la repetición de un ciclo de desarrollo muy corto: primero el desarrollador escribe un (inicialmente en su defecto) automatizado caso de prueba que define una mejora deseada o una nueva función, entonces produce la cantidad mínima de código para pasar esa prueba, y finalmente refactoriza el nuevo código de normas aceptables. Kent Beck, a quien se atribuye haber desarrollado o 'redescubierto' la técnica, declaró en 2003 que TDD alienta diseños simples e inspira confianza.
Desarrollo basado en pruebas está relacionada con los conceptos de programación de pruebas de primera de la programación extrema, iniciadas en 1999, pero más recientemente ha creado interés más general por derecho propio. Los programadores también aplican el concepto de mejorar y depurar código heredado desarrollado con técnicas más antiguas. (Wikipedia, 2005)
Revista digital: Test Driven Development
Desarrollo guiado por pruebas de software, o Test-driven development (TDD) es una práctica de ingeniería de software que involucra otras dos prácticas: Escribir las pruebas primero (Test First Development) y Refactorización (Refactoring). Para escribir las pruebas generalmente se utilizan las pruebas unitarias (unit test en inglés).
En primer lugar, se escribe una prueba y se verifica que las pruebas fallan. A continuación, se implementa el código que hace que la prueba pase satisfactoriamente y seguidamente se refactoriza el código escrito. El propósito del desarrollo guiado por pruebas es lograr un código limpio que funcione. La idea es que los requisitos sean traducidos a pruebas, de este modo, cuando las pruebas pasen se garantizará que el software cumple con los requisitos que se han establecido. (Wikipedia, 2005)
Cuando hacemos una aplicación, es muy importante probar el código. Una solución es ejecutar muchas veces la aplicación cuando está acabada, pero especialmente mientras la estamos desarrollando, y probar mucho, muchas veces, una y otra vez. Otra solución más eficiente (y menos aburrida), consiste en hacer test automáticos de prueba, que se ejecuten automáticamente cada vez que compilamos. De esta forma, sin que nos cause ningún trastorno, nuestra aplicación se estará probando sola una y otra vez. (Chuidiang, 2007)
Revista digital: Test Driven Development
1. - Añadir una prueba
En desarrollo basado en pruebas, cada nueva función comienza con la escritura de un ensayo. Para escribir un ensayo, el desarrollador debe entender claramente las especificaciones y requisitos de la función. El desarrollador puede lograr esto a través de casos de uso y casos de uso para cubrir los requisitos y condiciones de excepción, y puede escribir la prueba en cualquier prueba de marco es adecuado para el entorno de software. Podría ser una versión modificada de una prueba existente. Esta es una característica diferenciadora de desarrollo basado en pruebas frente a las pruebas unitarias escrito después del código está escrito: hace que el foco revelador sobre los requisitos antes de escribir el código, una diferencia sutil pero importante.
2. - Ejecute todas las pruebas y ver si la nueva falla Esto valida que el instrumento de prueba está funcionando correctamente, que la nueva prueba no pasa por error sin necesidad de ningún nuevo código, y que la característica requerida no existe ya. Este paso también prueba la prueba en sí, en sentido negativo: se descarta la posibilidad de que la nueva prueba siempre pasa, y por lo tanto no tiene ningún valor. La nueva prueba también falla por la razón esperada. Este paso aumenta la confianza de los desarrolladores que la prueba de la unidad está poniendo a prueba la restricción correcta, y pasa sólo en los casos previstos.
Revista digital: Test Driven Development
3. - Escriba un cierto código
El siguiente paso es escribir un código que hace que la prueba para pasar. El nuevo código escrito en esta etapa no es perfecto y puede, por ejemplo, pasar la prueba de una manera poco elegante. Eso es aceptable, ya que será mejorado y perfeccionado en el paso 5. En este punto, el único propósito del código escrito es para pasar la prueba; no más lejos (y por lo tanto no probado) funcionalidad debería predecirse ni 'permitido' en cualquier etapa.
4. - Ejecutar pruebas Si todos los casos de prueba ahora pasan, el programador puede estar seguro de que el nuevo código cumple con los requisitos de la prueba, y no se rompe o se degradan funciones existentes. Si no lo hacen, el nuevo código debe ser ajustado hasta que lo hagan.
Revista digital: Test Driven Development
5. - Código refactor
La base de código en crecimiento debe ser limpiado regularmente durante el desarrollo basado en pruebas. Nuevo código puede ser movido de donde estaba cómodo para pasar una prueba a donde pertenece más lógica. La duplicación se debe quitar. Objeto , clases , módulos , var iables y métodos nombres deben representar claramente su propósito y uso actual, se añade una funcionalidad adicional . A medida que se añaden características, cuerpos de los métodos pueden ser más largas y otros objetos grandes. Ellos se benefician de ser divididos y sus partes cuidadosamente nombrados para mejorar la legibilidad y mantenibilidad , que será cada vez más valioso más adelante en el ciclo de vida del software, las Jerarquías de herencia pueden ser reorganizadas para ser más lógico y útil, y tal vez se beneficien de reconocidos patrones de diseño. Hay pautas específicas y generales de refactorización y para la creación de un código limpio. Por continuamente re-ejecutar los casos de prueba a través de cada fase de la refactorización, el desarrollador puede estar seguro de que el proceso no está alterando cualquier funcionalidad existente.
6. - Repita Comenzando con otra nueva prueba, el ciclo se repite entonces para impulsar la funcionalidad. El tamaño de los pasos siempre debe ser pequeña, con tan pocos como 1 a 10 ediciones entre cada ejecución de prueba. Si el nuevo código no satisface rápidamente una nueva prueba, u otras pruebas de romperse de repente, el programador debe deshacer o revertir con preferencia a excesiva depuración . La integración continua ayuda, proporcionando puestos de control revertibles. Al usar bibliotecas externas, es importante no hacer incrementos que son tan pequeñas como para ser eficaz sólo probar la propia biblioteca, a menos que haya alguna razón para creer que la biblioteca está libre de errores o no está suficientemente característicacompleto para servir a todos las necesidades de software en fase de desarrollo. (Wikipedia, 2005)
Revista digital: Test Driven Development
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. El poder del TDD radica en la capacidad de avanzar en pequeños A pesar de los elevados pasos cuando se necesita. Permite requisitos iniciales de aplicar esta que un programador se centre en la metodología, el desarrollo guiado tarea actual y la primera meta es, a por pruebas (TDD) puede menudo, hacer que la prueba pase. proporcionar un gran valor Inicialmente no se consideran los añadido en la creación de produciendo casos excepcionales y el manejo de software, errores. Estos, se implementan aplicaciones de más calidad y en después de que se haya alcanzado la menos tiempo. Ofrece más que funcionalidad principal. Otra ventaja una simple validación del es que, cuando es utilizada cumplimiento de los requisitos, correctamente, se asegura de que también puede guiar el diseño de todo el código escrito está cubierto un programa. Centrándose en por una prueba. Esto puede dar al primer lugar en los casos de programador un mayor nivel de prueba uno debe imaginarse cómo los clientes utilizarán la confianza en el código. funcionalidad (en este caso, los casos de prueba). Por lo tanto, al programador solo le importa la interfaz y no la implementación. Esta ventaja es similar al diseño por convenio pero se parece a él por los casos de prueba más que por las aserciones matemáticas. (Wikipedia, 2014)
Revista digital: Test Driven Development
La mejor manera de aprender TDD es practicando, así que vamos a realizar una pequeña introducción utilizando un ejemplo.
Imaginemos que tenemos que implementar un banco, lo más importante del banco son las cuentas de sus clientes, así que tenemos estos requisitos. El saldo inicial de la cuenta debe ser 0 El saldo de la cuenta no puede ser negativo Así que manos a la obra. Crear el proyecto Lo primero de todo es tener el workspace de eclipse en C:\xampp\httdocs ahora lo que hacemos es crear un nuevo proyecto llamado “CuentaBancariTDD” y creamos una carpeta para guardar los tests.
Ahora escogemos el requisito el saldo inicial de la cuenta debe ser 0. Y vamos a crear el primer test
Revista digital: Test Driven Development
Requisito 1: el saldo inicial de la cuenta debe ser 0
Creando el 1º test
Si analizamos el requisito el saldo inicial de la cuenta debe ser 0, vemos que tenemos que ser capaces de crear una cuenta, es decir crear un objeto o algo de tipo cuenta. También debemos ser capaces de obtener el saldo disponible en dicha cuenta. Bien, llegados a este punto vamos a crear un test que cree un nuevo objeto cuenta y vamos a hacer un assert para comprobar que el estado justo después de crear el objeto es 0; Aquí tenemos el código: <?php
require_once ‘/../src/CuentaBancaria.php’; class CuentaBancaria_Test extends PHPUnit_Framework_TestCase { public function testBalanceIncialEsCero ( ) { $this -> cb = new CuentaBancaria(); $this -> assertEquals ( 0 , $this -> cb -> getBalance ( ) ); } }
Revista digital: Test Driven Development
Creando el código
Ahora tenemos que crear el código necesario para pasar la prueba. Crearemos una nueva clase donde llamada cuenta bancaria con la que podremos crear una cuenta. Esta clase de momento tendrá solamente una función que devuelve el balance de la cuenta.
<?php class CuentaBancaria { protected $balance = 0; public function getBalance() { return $this -> balance; } }
Ya tenemos creado nuestro código: Ahora el test funciona Solo nos queda probar que todo está correcto, para ello ejecutamos el test. Como vemos con “require_once” hemos creado una nueva carpeta llamada src donde albergamos el código de la clase Cuenta bancaria.
Refactor De momento no hay mucho por refactorizar, así que vamos a por el siguiente requisito.
Revista digital: Test Driven Development
Requisito 2: El saldo de la cuenta no puede ser negativo Bueno pues vamos a la carga con el 2º requisito.
Creando el test
Podemos ver que para que el saldo sea negativo, debemos implementar un mecanismo (función) para retirar dinero de la cuenta. Por otro lado vamos a probar las excepciones, es decir, si intentamos sacar dinero teniendo la cuenta 0 vamos a tener una excepción ya que se incumple un requisito. Básicamente este es el código: public function testBalanceNoPuedeSerNegativo ( ) { $this -> cb = new CuentaBancaria(); try { $this -> cb -> retirarDinero ( 1 ); } catch ( Exception $e ) { $this -> assertEquals ( 0 , $this -> cb -> getBalance ( ) ) ; return ; } }
Probando que falla Ahora ejecutamos el test y vemos que falla.
Revista digital: Test Driven Development
Creamos el código
Vamos a crear 2 funciones, una para depositar dinero y otra para comprobar que el balance de la cuenta sigue siendo mayor que cero. protected function setBalance ($balance) { if ($balance >= 0) { $this -> balance = $balance; } else { throw new Exception(); } } public function depositarDinero ($balance) { $this -> setBalance ($this->getBalance( )+ $balance); return $this -> getBalance ( ); }
Pasar el test Comprobamos que ahora el test pasa.
Revista digital: Test Driven Development
Refactorizar
Esta es una de las cosas más difíciles, ya que hay que darse cuenta del código duplicado. Podemos ver que en cada uno de los test estamos creando una nueva cuenta bancaria. Podríamos crear un método setup que se ejecute antes de nuestros tests. En este método setup lo que podemos hacer es crear el entorno, en nuestro caso crear la cuenta bancaria. Así que allá vamos. Así quedaría nuestra clase de test: <?php require_once '/../src/CuentaBancaria.php'; class CuentaBancaria_Test extends PHPUnit_Framework_TestCase { protected $cb; protected function setUp() { $this -> cb = new CuentaBancaria(); } public function testBalanceIncialEsCero () { $this -> assertEquals ( 0 , $this -> cb -> getBalance () ) ; } public function testBalanceNoPuedeSerNegativo () { try { $this -> cb -> depositarDinero ( 1 ); } catch ( CuentaBancariaException $e ) { $this -> assertEquals ( 0 , $this -> cb -> getBalance ( ) ) ; return ; } } }
Revista digital: Test Driven Development
Por otro lado también refactorizaremos el código, en nuestro caso de momento no hay nada que refactorizar. Aunque debemos darnos cuenta de que esto no está acabado, podemos depositar dinero, pero ¿y retirarlo? Todavía nos falta crear un test para que el requisito 2 se cumpla. Este es el test: public function testBalanceNoPuedeSerNegativo2() { try { $this -> cb -> retirarDinero ( 1 ) ; } catch ( Exception $e ) { $this -> assertEquals ( 0 , $this -> cb -> getBalance ( ) ) ; return 0 ; } }
Comprobamos que no pasa:
Revista digital: Test Driven Development
Creamos el c贸digo:
public function retirarDinero ( $balance ) { $this -> setBalance ( $this -> getBalance ( ) - $balance) ; return $this -> getBalance ( ) ; }
Y vemos que ya pasa el test ya si pasa
Comprobamos que no pasa: (L贸pez, 2013)
Revista digital: Test Driven Development
chuidiang. (Febrero de 4 de 2007). Ejemplos java y C/linux. Recuperado el 8 de Abril de 2015, de Ejemplos java y C/linux: http://www.chuidiang.com/java/herramientas/testautomaticos/tdd-test-driven-development.php L贸pez, J. (06 de Junio de 2013). JesusLC. Obtenido de http://jesuslc.com/2013/06/24/529/ Wikipedia. (Abril de 09 de 2005). Wikipedia. Obtenido de http://en.wikipedia.org/w/index.php?title=Testdriven_development&action=history Wikipedia. (21 de Diciembre de 2014). Wikipedia. Obtenido de http://es.wikipedia.org/w/index.php?title=Desarrollo_guiado_ por_pruebas&action=history
Revista digital: Test Driven Development