JavaScript es un lenguaje establecido y la web es la plataforma principal de hoy en día, donde hemos visto la aparición de las aplicaciones de una sola página, la proliferación de los frameworks MVC como AngularJS o Backbone.js, el uso de JavaScript del lado del servidor con Node.js e incluso aplicaciones móviles creadas únicamente utilizando HTML, CSS y JavaScript con tecnologías como PhoneGap.
Desde sus humildes inicios JavaScript se ha encargado de servir como lenguaje para manipular la data y validando la misma en los formularios en HTML y en la actualidad es usado para construir las poderosas aplicaciones que podemos ver en la web. Viendo esto se puede decir que JavaScript ha recorrido un largo camino así como las herramientas que han ido apareciendo para lograr que tengamos la misma calidad como si estuviéramos en otros lenguajes.
Una de estas herramientas es Jasmine, que no es más que un framework de desarrollo orientado a comportamientos y que nos permite crear pruebas unitarias automatizadas para el lenguaje de programación JavaScript. Antes de entrar de lleno con esta herramienta veamos los antecedentes que llevaron al desarrollo de la misma así como conceptos claves para entender cómo funciona JavaScript.
JavaScript, lo malo
Hoy en día nadie duda del poder de JavaScript, sin embargo existen complicaciones cuando se trabaja del lado del cliente y una de las razones obvias es que no podemos controlar el ambiente de ejecución del mismo. En el servidor no tenemos este problema ya que podemos ejecutar una versión específica de Node.js pero en el caso del navegador web no podemos decirle al usuario que use una versión específica de Chrome o Firefox.
El lenguaje JavaScript se encuentra definido bajo las especificaciones ECMAScript por lo que cada navegador puede tener su propia implementación del entorno para ejecutar el mismo, haciendo que existan pequeñas diferencias o bugs entre los mismos. Cada objeto de JavaScript es mutable por lo que no tenemos ningún tipo de control para prevenir que un módulo sobre escriba piezas de otros, para ilustrar esto veamos un pequeño segmento de código donde podemos ver lo fácil que es sobre escribir la función global console.log:
console.log('prueba'); console.log = 'break'; console.log('prueba');Veamos la respuesta por consola, donde claramente podemos ver el error ya que hemos sobre escrito la función:
Esta forma de ser del lenguaje fue una decisión que se tomó en el diseño del mismo, ya que permitía a los desarrolladores agregar funcionalidades faltantes al mismo, pero dado esta versatilidad es relativamente más fácil cometer errores, incluso una versión más reciente del lenguaje introdujo la función Object.seal que prevenía esto pero su soporte solo se extendía a unos pocos navegadores.
Otro de los problemas que presentamos con JavaScript es el manejo de los tipos, en otros lenguajes una expresión como '1' + 1 probablemente levante un error, pero en JavaScript esto daría como resultado 11. Esto puede llevar a unos cuantos problemas difíciles de encontrar, por ejemplo, supongamos que tenemos lo siguiente:
var a = 1, b = '5', c = 4, d = 2; var resultado = a + b + c * d; console.log(resultado);Veamos la respuesta por la consola cuando ejecutamos nuestro código en el navegador:
Como vemos el resultado fue un string, por lo que si estábamos esperando un número en alguna función o rutina en especial esto puede ocasionar un problema y encontrar este error puede suponer perder unas cuantas horas de nuestro preciado tiempo de desarrollo.
Es importante mencionar que los puntos que acabamos de mencionar no es una razón para no usar JavaScript, es simplemente ver donde el mismo tiene algunas debilidades pero esto no significa que sea un mal lenguaje, incluso podemos asegurar que las posibilidades que nos presenta el mismo son infinitas en cuanto al desarrollo de aplicaciones y lo que es mejor aún disponemos de herramientas que nos ayudarán con las mejores prácticas del mismo.
Jasmine y el desarrollo orientado a comportamientos
Como mencionamos, Jasmine es un pequeño framework que nos ayuda con nuestras pruebas unitarias dentro de nuestros desarrollos y que utiliza la filosofía del desarrollo orientado a comportamientos el cual explicaremos más adelante, pero antes de seguir veamos un concepto importante y es que son las pruebas unitarias.
Es por ello que los creadores de Jasmine reestructuran esta manera tradicional de realizar pruebas, en el cual el desarrollador era dejado sin un panorama claro de por dónde empezar en el proceso de pruebas, sin saber que probar y que tan grande podría ser un módulo de pruebas o incluso como llamarían a una de estas pruebas. Por ejemplo, si usamos la filosofía de Jasmine para realizar las pruebas, supongamos que tenemos un reproductor de música el cual tendrá el criterio de aceptación siguiente: Dado el reproductor, cuando una canción es pausada entonces el reproductor debe indicar que la canción fue pausada.
Entonces podemos tomar el criterio y dividirlo de la siguiente manera:
- Dado (Un contexto inicial)
- Cuando (El evento ocurre)
- Entonces (Una acción es tomada)
describe("Reproductor", function() { describe("Cuando la cancion es pausada", function() { it("Debe indicar que la cancion es pausada", function() { }); }); });Como podemos ver nuestro criterio fue trasladado a Jasmine sin muchos problemas, donde podemos decir que cada criterio se traduce a una prueba unitaria.
Obteniendo Jasmine
Ya pudimos darle un vistazo a como Jasmine maneja los criterios y los traduce a su sintaxis creando las pruebas unitarias para el mismo, pero para poder llegar allí veamos primero cómo obtener primero el framework. Para ello nos dirigimos a la página del proyecto y descargamos el mismo:
Al descomprimirlo debemos dirigirnos a la carpeta de dist, allí encontraremos todas distribuciones de Jasmine hasta la fecha, donde para poder empezar a utilizar el mismo debemos seleccionar la distribución que queramos, preferiblemente la más reciente y la descomprimimos en la carpeta de nuestro proyecto, ingresamos en la carpeta y ejecutamos el archivo SpecRunner.html:
Jasmine nos incluye por defecto unos ejemplos de unas pruebas unitarias, donde el archivo SpecRunner.html es el encargado de enlazar el código de Jasmine el cual incluye los archivos fuentes y los archivos para las pruebas, veamos el contenido del mismo:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Jasmine Spec Runner v2.2.0</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.2.0/jasmine_favicon.png"> <link rel="stylesheet" href="lib/jasmine-2.2.0/jasmine.css"> <script src="lib/jasmine-2.2.0/jasmine.js"></script> <script src="lib/jasmine-2.2.0/jasmine-html.js"></script> <script src="lib/jasmine-2.2.0/boot.js"></script> <!-- include source files here... --> <script src="src/Player.js"></script> <script src="src/Song.js"></script> <!-- include spec files here... --> <script src="spec/SpecHelper.js"></script> <script src="spec/PlayerSpec.js"></script> </head> <body> </body> </html>Como vemos es bastante simple y nos permite definir una estructura base para nuestras pruebas, dándonos una ayuda de por dónde empezar en este mundo de las pruebas unitarias. No está de más decir que es una buena idea que le demos un vistazo al código de nuestra distribución de Jasmine para así irnos familiarizándonos con la forma en que el mismo trabaja.
Es importante mencionar que Jasmine no solo se limita a código escrito con JavaScript puro, podemos probar aquellas aplicaciones construidas con Backbone.js o AngularJS, incluso su versatilidad va mucho más allá y nos permite realizar pruebas del lado del servidor en el caso que estemos utilizando Node.js.
Con esto finalizamos este tutorial, donde pudimos dar nuestros primeros pasos con Jasmine, paseándonos un poco por la motivación de crear herramientas para hacer pruebas sobre JavaScript y como el desarrollo orientado a comportamientos nos ayuda a crear mejores pruebas, viendo además como Jasmine es un framework bastante flexible para realizar pruebas, permitiéndonos usar la misma instancia para probar todo tipo de código en JavaScript en nuestras aplicaciones.