Como testear aplicaciones en Ember.js

0
6032

Como testear una aplicación de Ember.js con Jasmine

0. Índice de contenidos.

1. Entorno

Este tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil Intel Core 2 Duo CPU T8100 @ 2.10GHz x 2
  • Sistema Operativo: Ubuntu 12.04 LTS x32
  • Sublime Text 2

2. Introducción

Los cambios que han sucedido en los últimos años han propiciado el crecimiento del uso de Javascript, así como el tamaño de los programas escritos con Javascript, lo cual nos ha obligado a replantearnos la manera en la que programamos con Javascript.

Por ello, y aprovechando los conocimientos adquiridos en el lado servidor, se está intentando traspasar las buenas practicas ya logradas al lado del cliente.

Practicas como pueden ser la implementación de Test Unitarios y de Integración, el uso de herramientas de automatización a la hora de desplegar las aplicaciones y demás herramientas para asegurar la calidad del código.

Es importante comprender que Javascript es un lenguaje dinámico, de tipado débil, lo cual no lo hace ni mejor ni peor, y hay que tratarlo como tal, para lo bueno y para lo malo.

Este tutorial hará uso de diferentes herramientas y frameworks para conseguir esas metas, las herramientas que vamos a usar son las siguientes:

  • Ember.js: Es un framework MVC que nos aporta abstracciones a la hora de conseguir seguir el patrón MVC, además de otras herramientas que facilitaran el desarrollo de aplicaciones SPA ( Single Page Application ) . Si quieres saber mas sobre Ember puedes echar un vistazo a los siguientes tutoriales: Primeros Pasos con Ember y Primera Aplicación Ember
  • Require.js: Require.js es un framework de Javascript que nos permite modularizar nuestro código, de manera lógica y física, aparte de ofrecernos la posibilidad de cargar módulos «on-demand», lo que nos vendrá muy bien a medida que nuestra aplicación vaya creciendo. Si quieres saber mas sobre Require.js, o sobre como hemos aplicado Require a nuestro proyecto, puedes mirar los siguientes tutoriales: Introduccion a Require y Modularizar tu aplicación de Ember con Require
  • Jasmine: Jasmine nos ofrece una serie de herramientas con las que podremos realizar nuestros test, además de proporcionarnos la posibilidad de agruparlos y nos ofrecerá distintos plugins con los que acoplar nuestros test a nuestro sistema de despliegue automático favorito. Puedes ver un tutorial sobre Jasmine en el siguiente enlace.Primeros pasos con Jasmine
  • Maven: Maven es una herramienta que nos permite gestionar y construir proyectos en Java, este tutorial se centrará en como instalar y configurar el plugin de Jasmine para que pase los test de Javascript a la vez que los de Java a la hora de desplegar nuestra aplicación.

3. Mavenizando nuestro proyecto

Lo primero que vamos a hacer es integrar nuestro Proyecto dentro de un proyecto de Maven, nuestra aplicación residirá en «src/main/webapp/scripts/app» siendo main.js nuestro punto de entrada, tendremos dos archivos de configuración, uno para el entorno de producción y otro para el de pruebas.

Por último, los test residirán en el archivo test/specs, en el pom.xml tenemos que añadir el plugin de Jasmine y la configuración especifica del plugin.

       
   
     com.github.searls
     jasmine-maven-plugin
     1.3.1.1
     
       
         
           test
         
       
     
     
       
       REQUIRE_JS
       
       ${project.basedir}/src/main/webapp/scripts
       
       ${project.basedir}/src/test/specs
       
       
       
       
         ${project.basedir}/src/main/webapp/scripts/libs/requirejs/2.1.2/require.js
         ${project.basedir}/src/main/webapp/scripts/libs/jquery/1.9.1/jquery.js
         ${project.basedir}/src/main/webapp/scripts/libs/handlebars/1.0.rc.3/handlebars.js
         ${project.basedir}/src/main/webapp/scripts/libs/ember/1.0.0-rc.2/ember.js
         ${project.basedir}/src/main/webapp/scripts/config_test.js
       
     
   
 

Como nuestro proyecto hace uso de Require.js para cargar nuestros módulos, hay una dificultad añadida a la hora de usar Jasmine, así que hacemos uso de la opción que nos brinda el plugin de Maven.

Por último pre-cargamos nuestra librerías para evitarnos problemas a la hora pasar los tests.

Una vez tengamos todo listo, hacemos un «mvn install» para que se nos instalen las dependencias necesarias para el plugin.

Para pasar los test de Javascript tenemos dos opciones, pasarlos junto a los test de Java, usando la directiva «mvn test» o bien usar la propia directiva que nos ofrece el plugin de Jasmine «mvn jasmine:bdd».

A la hora de hacer TDD/BDD, la segunda opción se presenta muy útil, pues nos inicia un servidor, en el cual podemos pasar todas nuestros test y ver los resultados en tiempo real, actualizándose cuando hacemos cambios en cualquier test o archivo de la aplicación.

Probamos con el comando mvn jasmine:bdd que todo se ha instalado correctamente, en la consola nos debería mostrar la dirección en la que se ha creado nuestro servidor el cual nos permitirá ver los test, en un principio deberíamos ver algo así:

¡Es hora de hacer nuestro primer test!

4. Haciendo Test con Jasmine para nuestra aplicación con Ember y Require

Es importante tener en cuenta que al estar usando Require y Ember, la manera en la que tenemos que hacer los test se tiene que adaptar a las tecnologías usadas.
Para testear con Require, es recomendable convertir los test en módulos de Require, en los cuales puedes declarar las dependencias y así mantener un nivel de encapsulación óptimo para el entorno de pruebas que nos asegurará mejores resultados.

El primer test que vamos a hacer va a comprobar que se están cargando todas las librerías.

Para ello crearemos un fichero Javascript en nuestra carpeta de test, en el ejemplo la carpeta se encuentra en «src/main/test/specs»

define(function() {
  describe("Comprobación de que las librerías se hayan cargado correctamente", function() {
    it("Ember se ha cargado", function() {
      expect(Ember).not.toBeUndefined();
    });
    it("jQuery se ha cargado", function() {
      expect($).not.toBeUndefined();
    });
    it("Handlebars se ha cargado", function() {
      expect(Handlebars).not.toBeUndefined();
    });
    
    it("Require se ha cargado", function() {
      expect(require).not.toBeUndefined();
    });
  });
});

Gracias a la sintaxis de Jasmine, los test son muy legibles, y auto-explicativos, lo cual facilita mucho la tarea de compartir los test con otras personas.

Si recargamos el navegador, la pagina que nos había preparado Maven ahora debería mostrar algo así:

A la hora de hacer test unitarios de nuestras aplicaciones de Ember, hay que tener en cuenta como funciona Ember, ya que al iniciar la aplicación, Ember crea una serie de «Listeners» de eventos que tienen un numero alto de probabilidades de chocar con otros frameworks y herramientas como pueden ser Maven o Jasmine.

Por ello Ember provee de un método llamado deferReadiness(), que nos permitirá preparar la aplicación para ser testeada, pero sin interferir con el resto de frameworks, en el siguiente ejemplo, podemos ver como podríamos testear los métodos de un controlador de Ember.

El código del controlador a testear lo podemos encontrar aquí , y el código del test sería el siguiente:

define(['controllers/MenuSelectColorController'], function(menuSelectColorController) {

  describe("Conjunto de test que prueban el MenuSelectController", function(){

    var stateManager = jasmine.createSpyObj('stateManager', ['set','saveState']);

    var dummyObject = {};

    window.App = Ember.Application.create({
      ColorsController : dummyObject,
      ColorController : dummyObject
      menuSelectColorController : menuSelectColorController
    })

    App.stateManager = stateManager;

    /*
      By default, calling `Ember.Application.create()` will automatically initialize
      your application by calling the `Ember.Application.initialize()` method. If
      you need to delay initialization, you can call your app's `deferReadiness()`
      method. When you are ready for your app to be initialized, call its
      `advanceReadiness()` method.
    */
    App.deferReadiness();

    var controlador = menuSelectColorController.create({
      container : App.__container__
    })

    var color = {
      name : "red"
    }

    it("Cuando el controlador recibe el evento lo propaga correctamente al State Manager" ,function(){
      controlador.changeSelectedColor(color)

      expect(stateManager.set).toHaveBeenCalled();
      expect(stateManager.saveState).toHaveBeenCalled();
    });
  });
})

Línea 1 : Lo primero que hacemos es definir las dependencias que tendría el test, en este caso la única dependencia fuera de las librerías que estamos usando es la del propio controlador que vamos a testear.

Línea 5 : Creamos un espía que nos dirá si el Controlador que estamos usando usa los métodos del otro objeto.

Línea 7 : Creamos un objeto vacío que le pasaremos a Ember como si fuesen otros dos objetos. Debido a que el Controlador no usa en ningún momento ninguno de esos dos objetos, Ember no comprueba que esos objetos tengan métodos ni nada, solo comprueba que las variables estén definidas.
( Estos dos objetos son necesarios para la vista, ya que son los encargados de mostrar la lista de colores, pero el controlador no los usa para nada )

Línea 9 : Iniciamos la aplicación en el namespace global, y le pasamos los objetos que hemos creado y el objeto que deseamos testear.

Línea 26 : Iniciamos manualmente el controlador.

Líneas 34-39 : Realizamos el test que comprobará el correcto funcionamiento de nuestro Controlador.

5. Conclusiones

Como se puede observar, hacer test para nuestras aplicaciones de Ember conlleva escribir un poco mas de código de la cuenta, lo bueno es que Ember lleva en su interior una serie de Test de Integración que nos ayudarán a completar nuestra Suite de Test, de manera que nos podamos centrar mas en los test unitarios de las funciones que añadamos nosotros.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad