Escribiendo una Aplicación usando TDD (Parte 2) Primera lista

Published on Author lopezLeave a comment

Siguiente post en esta serie
Anterior post en esta serie

Gracias a un comentario de @MartinSalias, en mi post anterior, elegí para desarrollar este ejemplo un dominio simple: mi biblioteca personal, mis libros. En esta primera iteración de código, quiero listar los temas de los libros: Física, Matemáticas, Biología, Literatura… (similar a los génereos del ejemplo MvcMusicStore de @jongalloway).

Primero, creé una solución ASP.NET MVC 2 (estoy usando Visual Studio 2008) (el código de este post, como siempre, queda en mi AjCodeKatas Google Project, en el directorio trunk/AppTdd/Step01)

Luego, agregué un proyecto de test:

A este proyecto le agregué referencias a System.Web.Mvc and MyLibrary.Web.

Agregué un test:

Limpié el código de la clase generada por el wizard, removiendo código no usado. Quedó:

namespace MyLibrary.Web.Tests.Controllers
{
    using System;
    using System.Text;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    [TestClass]
    public class GenreControllerTests
    {
    }
}

Ahora, agregué mi primer test:

        [TestMethod]
        public void GetGenres()
        {
            IList<Genre> genres = new List<Genre>()
            {
                new Genre() { Name = "Mathematics" },
                new Genre() { Name = "Physics" },
                new Genre() { Name = "Biology" },
                new Genre() { Name = "Literature" }
            };
            GenreController controller = new GenreController(genres);
            ActionResult result = controller.Index();
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(ViewResult));
            ViewResult viewResult = (ViewResult)result;
            Assert.IsInstanceOfType(viewResult.ViewData.Model, typeof(IList<Genre>));
            Assert.AreSame(genres, viewResult.ViewData.Model);
        }
		

La idea del test: crear el controlador, alimentarlo de una lista de temas, y luego invocar su acción Index. Hecho eso, controlar el resultado. A esta altura, el código no compilaba: el controlador no existía, no había clase Genre. Así que escribí esas clases. La clase Genre, en el directorio Model del proyecto MyLibrary.Web:

    public class Genre
    {
        public string Name { get; set; }
    }

Un controlador simple GenreController (agregado con click derecho sobre el directorio Controllers):

El wizard produjo este código:

    public class GenreController : Controller
    {
        //
        // GET: /Genre/
        public ActionResult Index()
        {
            return View();
        }
    }

Lo modifiqué para que tenga el constructor que necesito en el test:

    public class GenreController : Controller
    {
        public GenreController()
        {
        }
        public GenreController(IList<Genre> genres)
        {
        }
        public ActionResult Index()
        {
            return View();
        }
    }
	

Noten que mi intención es compilar el test, no que fuencione: la lista de temas no es usada por esta primer implementación de controlador. Con todos estos cambios, pude compilar la solución y ejecutar el test:

 

 

 

 

El resultado:

El problema:

Como esperaba. Esto es parte del ciclo TDD: compilar, rojo, y ahora, hay que ir por el verde.

Cambié el controlador (su interfaz ya estaba completa):

    public class GenreController : Controller
    {
        private IList<Genre> genres;
        public GenreController()
        {
        }
        public GenreController(IList<Genre> genres)
        {
            this.genres = genres;
        }
        public ActionResult Index()
        {
            return View(genres);
        }
    }

Y ahora, el resultado es:

 

 

Triunfo de la mente sobre la materia! 馃槈

Ahora, es tiempo de refactoring. Bien, no tengo mucho para hacer ahora (me llega un comentario en mi post en inglés de @MartinSalias, sugiriendo cambios en la nomenclatura, bien, quedará para el próximo paso). Podría mejorar alguna variable, nombre. La principal pieza faltante: la vista. Nota: el controlador no está preparado, aún, para ser consumido por una vista. No hay quien le provea los temas en ejecución. En el test, usé un constructor que se los provee, pero ASP.NET MVC crearía la instancia del controlador usando el constructor sin parámetros.

Próximos pasos: mejorar el controlador para usar una vista, algunas acciones CRUD con tests, y vistas.

Podrían preguntar: ¿dónde está el repositorio de los temas? ¿dónde están los libros? ¿y la base de datos? ¿y la capa de servicios (service layer)? ¿separación del dominio? Ok, son todas preguntas válidas y temas a tratar. Pero mi idea es mostrar, de forma incremental, con TDD, cómo podemos ir agregando todo eso a medida que aparezcan más requerimientos y especificaciones. Quiero que cada cosa que se agregue provenga del proceso de escribir test (ya sea de la especificación del test, o de la etapa de refactoring). Como escribí en mi anterior post, esta es una clase de aproximación arriba-abajo (top-down). En este caso, el dominio es simple, así que comienzo desde el tope de la presentación. Luego de este ejemplo simple, a desarrollar en varios post, cambiaré a un dominio menos simple. En ese caso, comenzaré por construir por tests al propio dominio, en lugar de la presentación.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *