my github
english | español
Waldo Urribarri HOME PROJECTS ABOUT ME


Probando aplicaciones RequireJS-Backbone.js-JQuery-Underscore usando Jasmine

jasmine

Probar el software es importante, mientras antes mejor. Trabajes en una aplicación pequeña o grande, podrías introducir bugs sin intención mientras hagas modificaciones, y tener pruebas (unitarias o funcionales) te ayudará a encontrarlos incluso durante el build, o por lo menos antes de ir a fase de QA. Esta vez te mostraré mi acercamiento a implementar pruebas en mi aplicación web ES5 que está estructurada usando RequireJS, Backbone.js, JQuery, y Underscore, usando una genial herramienta llamada Jasmine.

No cubriré cómo crear las pruebas ya que hay bastante documentación al respecto, sino cómo hacer el setup de todo para empezar a usarlas. Tenía un viejo proyecto que no tenía pruebas implementadas y quise intentar agregarlas.

Mi proyecto está estructurado de la siguiente forma:

/
|__ js/
|______ models/
|______ views/
|______ [otros archivos .js]
|__ node_modules/
|__ test/
|______ main.js
|______ SpecRunner.html
|__ index.html
|__ [todo lo demás]

Así que, lo primero es agregar el paquete jasmine en mi package.json. Sólo has cd en la raíz del proyecto y:

npm install –save-dev jasmine

Pista: Si te salen errores “Uncaught TypeError: Cannot read property 'spies' of undefined thrown” error, podrías volver a la versión 2.4.1. Usa npm install –save-dev jasmine@2.4.1 en cambio.

Una vez que tengas el paquete, es momendo de configurar nuestro SpecRunner. Personalmente, prefiero incluirlo en una carpeta /test. Hay distintas plantillas para crearlo, pero te mostraré la que usé:

<!DOCTYPE html>
  <html>
    <head>
      <meta charset="utf-8" />
      <title>Jasmine Spec Runner</title>
      <link rel="shortcut icon" type="image/png" href="../node_modules/jasmine-core/images/jasmine_favicon.png" />
      <link rel="stylesheet" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css" />
      <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js">
      </script>
      <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js">
      </script>
      <script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js">
      </script>
      <script type="text/javascript" src="../node_modules/requirejs/require.js" data-main="main">
      </script>
      <script>
            function includeBody() {
                xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    if (this.readyState == 4) {
                        if (this.status == 200 || this.status == 0) {
                            var idx1 = this.responseText.indexOf('<body');
                            var idx2 = this.responseText.indexOf('</body>');
                            var body = this.responseText.substring(idx1, idx2 + 7);
                            var container = document.createElement("div");
                            container.style.display = 'none';
                            container.innerHTML = body;
                            document.getElementsByTagName('body')[0].appendChild(container);
                        }
                    }
                } 
                xhttp.open("GET", '../index.html', true);
                xhttp.send();
            }
        </script>
  </head>
  <body>
    <script>includeBody();</script>
  </body>
</html>

Link a fuente completo: SpecRunner.html

Nota: La función includeBody() es algo especial para mi proyecto. Más sobre eso en un momento.

La primera parte del SpecRunner sólo carga el core de jasmine, y luego cargo require y mi configuración inicial.

require.config({
  baseUrl: '../', // to set the default folder
  paths: {
    'jasmine': ['./node_modules/jasmine-core/lib/jasmine-core/jasmine'],
    'jasmine-html': ['./node_modules/jasmine-core/lib/jasmine-core/jasmine-html'],
    'jasmine-boot': ['./node_modules/jasmine-core/lib/jasmine-core/boot'],

    //agrega todos los módulos que son requeridos dentro de tus models/views/etc
  },
  shim: {
    'jasmine-html': {
      deps: ['jasmine']
    },
    'jasmine-boot': {
      deps: ['jasmine', 'jasmine-html']
    }
  }
});

require(['jasmine-boot'], function () {
  require([
    'js/models/EntryAreaModel.spec'
    // agrega tus specs aquí
    ], function(){
      window.onload();
  })
});

Como puedes ver, en la sección 'paths', debes agregar los módulos de jasmine y también todos los demás módulos que podrían ser eventualmente requeridos por los tuyos. Luego en el require de abajo, agrega todos los specs que serán probados.

Link a fuente completo: main.js

Luego de esto, tus módulos de Backbone estarán disponibles para ser requeridos en tus pruebas. Ejemplo:

define(['js/models/EntryAreaModel'], function(EntryAreaModel) {
  describe('EntryAreaModel tests', function() {
    describe('new models', function() {
      var model = new EntryAreaModel();
      it('should have indentType property', function() {
        expect(model.get('indentType')).toBeDefined();
      });
      it('should have indents property', function() {
        expect(model.get('indents')).toBeDefined();
      });
      it('without params are valid', function() {
        expect(model.isValid()).toBe(true);
      });
    });
  });
});

Link a fuente completo: EntryAreaModel.spec.js

Ahora, puedes abrir tu SpecRunner.html en un browser para correr las pruebas y ver cualquier error.

Jasmine Spec Runner

Sobre la función includeBody()

Como las Views de Backbone necesitan un DOM para manipular y también los templates de Underscore para crear elementos, necesito agregar todo el body de mi index.html para de verdad poder ejecutar mis tests de Views. La mejor forma que se me ocurrió es incluir el body en mi SpecRunner. :) No estoy si esta es la forma correcta, pero funciona.

Espero que esto te ayude a echar a andar tus pruebas ;)


www.000webhost.com