JavaScript Visual Studio and TDD

La idea de esta entrada es demostrar lo fácil que puede ser trabajar usando TDD con JavaScript desde nuestro Visual Studio como cualquier otro proyecto de test que tengamos en nuestra solución.

Para este ejemplo utilizaré una aplicación ASP.NET MVC con QUnit  el framework de test unitarios que utiliza JQuery y para lanzar los test utilizo directamente Resharper como cuando utilizo otros frameworks como NUnit, MSTest, etc. Debo aclarar que para Visual Studio hay un test runner que lo podéis descargar desde Chutzpah si no tenéis la oportunidad de utilizar Resharper que personalmente me encanta.

Tanto para instalar QUnit como Chutzpah podemos utilizar Nuget desde nuestro proyecto.

TDD

La idea es que necesitamos un Objeto cliente que le podamos especificar diferentes propiedades como puede ser el Nombre, dirección y además añadir sus pedidos.

Test 1

Siguiendo el desarrollo guiado por pruebas, lo primero que tenemos que hacer es una prueba donde intentaremos definir el nombre del cliente.

Lo primero que necesito es poder crear un variable cliente para las pruebas y poderlo utilizar en todas las pruebas y comprobar que cumple con los requisitos. Para eso creo un contexto donde se agruparan todos los test y compartirán la variable cliente. Para esto utilizaré la función module de la librería QUnit.

///<reference path="../qunit.js" />
module("Client TDD", {
    setup: function () {
        this.Client = new Client();
        this.Client.Name = "Marc";
    },
    teardown: function () {
        this.testData = null;
    }
});

Esta función necesita primero el nombre del contexto y luego el objeto usado como el entorno del test. El objeto testEnvironment tiene una función setup que se lanza antes de cada test y podemos utilizar para crear las propiedades que necesitemos utilizar a lo largo de los múltiples test que utilicemos y un teardown que se ejecuta después de cada test que podemos utilizar para limpiar los datos.

Ahora si que podemos crear nuestro primer test.

test("Test Set Client Name", function () {
    equal("Marc", this.Client.Name, "el nombre es Marc");
});

Esta primer test comprueba si el cliente contiene una Propiedad Nombre y si su valor es «Marc» para eso utilizaremos una comprobación de igualdad “equal”.

Yo como he comentado antes utilizaré Resharper para lanzar mis Test. El resultado del primer test tiene que ser negativo como no podía ser de otra manera utilizando TDD.

Resharper nos abrirá un el navegador con el QUnit Test Suite, además de mostrarnos el resultado en nuestro Visual Studio.

Los Errores son clarísimos no tenemos creado el objeto Cliente:

  1. Setup failed on Test Set Client Name: ‘Client’ no está definido.
  2. Died on test #2: No se puede obtener valor de la propiedad ‘Name’: el objeto es nulo o está sin definir.

Pues ahora nos toca implementar el objeto que la prueba necesita para ser pasada con éxito.

Utilizaré un nuevo fichero javascript donde tendré el código que utilizaré en la aplicación y crearé un objeto cliente utilizando el patrón module, con una parte privada y otra pública.

var Client = function () {
    var _private = {};
    var _public = {};
    _public.Name = "";
    return _public;
};

Tenemos que añadir la referencia al script del código en el fichero donde se encuentran los test y ya podemos relanzar la prueba.

///<reference path="../qunit.js" />
///<reference path="../Demo/Client.js" />
module("Client TDD", { . . .

Todo Verde !!! El objeto Cliente ya está cogiendo forma y todo guiados inicialmente por una prueba de lo que esperábamos que fuera.

Test  2

Siguiendo con la definición de nuestro objeto ahora queremos poder definir una propiedad dirección que será objeto un poco más complicado.

module("Client TDD", {
    setup: function () {
        this.Client = new Client();
        this.Client.Name = 'Marc';
        this.Client.Address = {
            street: 'Gran Via',
            state: 'Barcelona',
            PostalCode: '08001' };
    },
. . .
test("Test Set Address", function () {
    equal({ street: "Gran Via", state: "Barcelona", PostalCode: "08001" },
        this.Client.Address,
        'The address is { street: "Gran Via", state: "Barcelona", PostalCode: "08001" }');
});

Como antes hasta que no añadamos esta propiedad al objeto cliente no pasará la prueba correctamente,

var _public = {};
    _public.Name = "";
    _public.Address = { street: "", state: "", PostalCode: "" };
    return _public;

Pero el test vuelve a fallar !!!

El test falla porque estamos comparando dos objetos que aunque tengan todas las propiedades con el valor igual, son dos objetos diferentes. Par este caso no nos sirve un simple equal y tendremos que hacer una comparación más profunda que nos servirá para objetos y arrays con deeEqual.

test('Test Set Address', function () {
    deepEqual({ street: 'Gran Via', state: 'Barcelona', PostalCode: '08001' },
        this.Client.Address,
        'The address is { street: "Gran Via", state: "Barcelona", PostalCode: "08001" }');
});

Test 3

Ahora nuestra intención es hacer un Get-Set y un Count de los pedidos del cliente.

test('Test Set.Get Orders', function () {
    this.Client.Set_Order({ Id: "12345", Name: "Rent Car", Total: 237.45 });
    expect(2);
    deepEqual(
        { Id: "12345", Name: "Rent Car", Total: 237.45 },
        this.Client.Get_Order(1),
        'The order is { Id: "12345", Name: "Rent Car", Total: 237.45 }');
    strictEqual(2, this.Client.Orders(), 'The client have 2 orders');

});

Como siempre en TDD la primera prueba falla porque falta definir las funciones en el objeto cliente.

Ampliamos el objeto y pasamos la prueba:

    _public.Set_Order = function (order) {
        _private.Orders.push(order);
    };
    _public.Get_Order = function (index) { return _private.Orders[index]; };
    _public.Orders = function () { return _private.Orders.length; };


Lo que hay que destacar de este test es que hemos definido dos pruebas en el mismo test con expect(2) y hemos hecho una comprobación estricta con resultado y tipo en el count con strictEqual.

Ya tenemos nuestro objeto completo y podríamos seguir con TDD por ejemplo haciendo alguna prueba asíncrona con asyncTest , pero si necesitáis más información sobre QUnit podéis consultar su documentación en http://docs.jquery.com/QUnit

Conclusión

Ya no tenemos excusa para no tener nuestro código JavaScript cubierto con pruebas unitarias garantizando la calidad y un código más mantenible. Con TDD podemos crear nuestros objetos javascript desde nuestros requerimientos y tener directamente garantizado su correcto funcionamiento a partir de nuetros requisitos y necesidades establecidas.

Un comentario en “JavaScript Visual Studio and TDD

Deja un comentario