tdd – Instituto FOC | Informática ONLINE | FP Informática ONLINE

Taller técnico: Metodología TDD

[youtube https://www.youtube.com/watch?v=b_KLN3DNuPg&w=560&h=315]

Al finalizar esta sesión serás capaz de:

  • Conocer la metodología TDD
  • Planteamiento de pruebas unitarias

 

Contenidos de la sesión:

  • Para poder conseguir los objetivos previstos en la sesión trataremos los siguientes contenidos con un enfoque práctico
    • Metodología TDD
    • Planteamiento de test unitarios
    • Test unitarios con phpUnit

¿Que es y para que nos sirven los TDD?

Un TDD (Test Driven Development) es una técnica de desarrollo software en la que primero pensamos en las pruebas que vamos a realizar y luego aplicar técnicas de refactorizamos para tener un código limpio.

Para elaborar estas pruebas lo que realizas primero son las pruebas unitarias que vamos a realizar y a continuación, en base a estas pruebas, realizamos la implementación de nuestro código. Después aplicamos la refactorización a nuestro código para tener una implementación lo mas limpia posible.

Vamos a realizar un ejemplo concreto para ver como aplicamos esta técnica

Supongamos que tenemos una aplicación donde estamos implementando la gestión de nuestro carrito de la compra. En nuestro carrito de la compra vamos a poder insertar cualquier articulo, y por cada articulo que nosotros añadamos se deberá actualizar el importe total. Tendremos en cuenta que si introducimos un elemento que ya se encuentra en  nuestro carrito lo que realizaremos es un incremento de las unidades.

Partimos de las siguientes clases:

La clase Item que nos va a servir para almacenar los distintos elementos del carrito

class Item
    {

        private String _nombre;

        private Decimal _pUnidad;

        private int _ctdad;

        public String Nombre
        {
            get { return _nombre; }
            set { _nombre = value; }
        }

        public Decimal PrecioUnidad
        {
            get { return _pUnidad; }
            set { _pUnidad = value; }
        }

        public int Ctdad
        {
            get { return _ctdad; }
            set { _ctdad = value; }
        }

        public Item()
        {
            Nombre = «»;
            Ctdad = 0;
            PrecioUnidad = 0;
        }

        public Item(String _n, int ctdad, Decimal precio)
        {
            Nombre = _n;
            Ctdad = ctdad;
            PrecioUnidad = precio;
        }

    }

Y la clase Carrito para gestionar los elementos que vamos añadiendo al carrito:

 class Carrito
    {

        private List<Item> carrito;
        private Decimal _precTotal;        

        public Carrito(){
            carrito = new List<Item>();
            _precTotal = 0;            
        }
        
    }

 

Si seguimos las normas del TDD primero vamos a diseñar las pruebas unitarias para los distintos requisitos que vamos a cumplir:

1.- Comprobar que el importe total es de 0 cuando no tenemos ningún elemento en la cesta.

La prueba unitaria que nosotros tendremos que realizar es la siguiente:

[TestMethod]
 public void CestaCompraVacia()
 {
 // Comprobamos
 Carrito c = new Carrito();
 Assert.AreEqual(0, c.ItemsCarrito); // Comprobamos que hay cero elementos
 Assert.AreEqual(true, c.carritoVacio); // Comprobamos que el precio es 0
 }

Ahora en nuestro código dentro de nuestra clase que gestiona el carrito completaremos su código con los siguientes propiedades:

public bool carritoVacio
 {
 get { return carrito.Count == 0; }
 }

public int ItemsCarrito
{
get { return carrito.Count; }
}

2.- Comprobamos que cuando insertamos un elemento se actualiza el precio total y el número de artículos

En este caso la prueba unitaria a realizar seria la siguiente:

public void Añadir1ItemCesta()
 {
 // Comprobamos
 Carrito c = new Carrito();
 c.AddItem(new Item("CD's Virgenes",1,5));
 Assert.AreEqual(5, c.PrecTotal);
 Assert.AreEqual(1, c.ItemsCarrito);
 }

Como el método de ItemsCarrito ya lo tenemos implementando como resultado de la prueba anterior lo único que tenemos que realizar es la propiedad para obtener el precio total

public Decimal PrecTotal
 {
 get { return _precTotal; }
 set { _precTotal = value; }
 }

y el método para añadir elementos al carrito:

public void AddItem(Item it)
{
_precTotal += it.PrecioUnidad * it.Ctdad;
carrito.Add(it);         
}

 

3.- Comprobamos que cuando insertamos varios elementos se actualiza el precio total y el número de artículos teniendo en cuenta que podemos incluir elementos repetidos.

        [TestMethod]
        public void AñadirVariosItemCesta()
        {
            // Comprobamos 
            Carrito c = new Carrito();
            c.AddItem(new Item("CD's Virgenes", 1, 5));
            c.AddItem(new Item("CD's Virgenes", 1, 5));
            c.AddItem(new Item("CD's Virgenes", 1, 5));
            c.AddItem(new Item("DVD's Virgenes", 1, 10));
            Assert.AreEqual(25, c.PrecTotal);
            Assert.AreEqual(2, c.ItemsCarrito);
        }

Si observamos, aparentemente podemos ejecutar la prueba para ya que tenemos todos los métodos y propiedades a utilizar correctamente. Al ejecutar la prueba veremos que esta prueba no la supera ya que cada item que hemos añadido los considera como un objeto nuevo. Por lo que tendremos que modificar el método AddItem para que compruebe si el item existe y en caso de que existe modificar la cantidad almacenada.

Para ello vamos a incorporar un método de busqueda de productos y modifcaremos el método AddItem de la siguiente forma:

private Item estaItem(String nombre)
        {
            
            foreach (Item it in carrito){
                if (it.Nombre == nombre)
                    return it;
            }
            return null;
        }

        public void AddItem(Item it)
        {
            Item encontrado = estaItem(it.Nombre);
            if (encontrado!=null)
            {
                encontrado.Ctdad += it.Ctdad;
            }
            else
            {                
                carrito.Add(it);
            }
            _precTotal += it.PrecioUnidad * it.Ctdad;
        }

Podemos observar que con esta técnica de desarrollo tenemos un control mas seguro sobre el cumplimiento de los requisitos que si primero desarrollamos y luego realizamos las pruebas.