miércoles, 5 de enero de 2011

Probando aplicaciones web con Zombie.js

http://www.flickr.com/photos/tohoscope/5086711384/Probar aplicaciones web modernas, con mucho scripting del lado cliente, es cada vez más complejo. El hecho de que la interfaz de usuario cambie dependiendo de las interacciones sin necesidad de pasar por el servidor genera la necesidad de realizar pruebas sobre el lado cliente.

El problema de esto es que la mayor parte de las herramientas para efectuar este tipo de pruebas requiere de una instancia de un browser real, lo que genera una dependencia fuerte y sobre todo, implica que cada prueba tarde más porque un browser demora un montón de tiempo en cargar y dibujar los elementos y tiene en cuenta montones de cosas que en realidad no necesitamos en la mayoría de los escenarios para hacer pruebas automatizadas.

Zombie.js se llama así porque es un entorno de prueba headless (sin cabeza; en realidad sin browser), y es muy rápido, además de brindar un API muy cómoda para escribir las pruebas.

La plataforma hace uso nuevamente de las ventajas de Node.js (más detalles en un post anterior) para recrear el entorno de un browser, incluyendo el DOM y características de HTML5, pero sin la necesidad de dibujar realmente nada, lo que le permite alcanzar velocidades totalmente diferentes.

Para lograr este entorno, Zombie combina varias librerías abiertas como JSDOM para emular el DOM, HTML5 para parsing, Sizzle para los selectores CSS y AJAXSLT para el soporte a XPath. Y el proyecto a su vez, también está abierto a quien quiera meter mano, alojado en GitHub.

Veamos un brevísimo ejemplo de cómo instanciar el entorno de un browser, navegar a una página, identificarse y verificar que la operación sea exitosa al llegar a una siguiente página de bienvenida.

var zombie = require("zombie");
var assert = require("assert");


// Carga la página desde el localhost
zombie.visit("http://localhost:3000/", function (err, browser) {


  // Completa email y password y confirma el formulario
  browser.
    fill("email", "zombie@underworld.dead").
    fill("password", "eat-the-living").
    pressButton("Sign Me Up!", function(err, browser) {


      // Al procesar el form, ve si fue a la página correcta
      assert.equal(browser.text("title"), "Welcome To Brains Depot");
    })
});

Como se ve, el API es muy sencilla y natural, y como siempre en Node, no hay llamadas bloqueantes; todo lo que pasa se maneja con callbacks, lo que hace también que correr una batería importante de pruebas sea más rápido en total, facilitando la ejecución más frecuente, lo que siempre eleva la calidad del proceso de desarrollo.