Cómo realizar tests de unidad con Javascript en un proyecto Ruby on Rails
Este post se basa en la presentación Adventures in JavaScript testing, de Thomas Fuchs, creador de script.aculo.us, y todo un maestro del Javascript.
Lo que se pretende es testear funciones de Javascript con una doble intención:
- comprobar que la funcionalidad implementada es la que se esperaba
- comprobar la compatibilidad en distintos navegadores y plataformas
Es decir, doble sentido: no sólo sería un test al estilo clásico, sino que también permite comprobar si nuestro Javascript está soportado por varios navegadores de un sólo plumazo (todos sabemos que ninguno implementa el estándar, y que cada uno entiende su Javascript).
Es más, como la ejecución de los test se realiza lanzando el navegador y abriendo la página del test en cuestíón, podemos ampliar la gama de navegadores introduciendo nuevas reglas en el Rakefile.
Para poder seguir este tutorial bastará con tener un proyecto Rails con algún fichero javascript que queramos testear.
En primer lugar necesitamos instalar el plugin de tests de javascript:
$ script/plugin install http://dev.rubyonrails.org/svn/rails/plugins/javascript_test
+ ./javascript_test/CHANGELOG
+ ./javascript_test/README
+ ./javascript_test/assets/prototype.js
+ ./javascript_test/assets/unittest.css
+ ./javascript_test/assets/unittest.js
+ ./javascript_test/generators/javascript_test/javascript_test_generator.rb
+ ./javascript_test/generators/javascript_test/templates/javascript_test.html
+ ./javascript_test/init.rb
+ ./javascript_test/lib/javascript_test.rb
+ ./javascript_test/tasks/javascript_test.rake
+ ./javascript_test/test/javascript_test_test.rb
+ ./javascript_test/test/test/javascript/failure_test.html
+ ./javascript_test/test/test/javascript/success_test.html
Hecho esto podemos comprobar que se ha instalado correctamente ejecutando la tarea de Rake:
$ rake test:javascripts
Skipping Safari, not supported on this OS
Skipping Internet Explorer, not supported on this OS
Si habéis obtenido esta respuesta podemos empezar a entrar en materia: imaginad que tenéis un fichero de Javascript que se llama apGeneral.js en la ruta por defecto de Rails (public/javascripts/). Pues bien, para generar un test de unidad para dicho fichero bastará con invocar al generador de código que incorpora Rails:
$ script/generate javascript_test apGeneral
create test/javascript
create test/javascript/apGeneral_test.html
Esto nos generará un directorio y un fichero HTML con la plantilla del test: un fichero HTML plano con los ficheros javascript correctamente enlazados y una zona de contenidos, en donde se cargaran los resultados de los test.
Aún falta dar un paso más para poder ejecutar el test, y es realizar el siguiente enlace simbólico (que la verdad es que no sé porqué no está automatizado):
Hecho esto la cosa cambia:
$ rake test:javascripts
Skipping Safari, not supported on this OS
/test/javascript/apGeneral_test.html on Firefox: SUCCESS
Skipping Internet Explorer, not supported on this OS
Y el resultado es que en Firefox se nos habrá abierto una página con el siguiente aspecto:

Ahora manos a la obra, estamos listos para realizar nuestro primer test.
Los tests los vamos a realizar sobre las funciones definidas en el fichero apGeneral. Por ejemplo, la clásica función toggle, que muestra y oculta un elemento del árbol DOM:
function toggle(id) {
if (document.getElementById(id).style.display == 'block') {
document.getElementById(id).style.display = 'none'
} else {
document.getElementById(id).style.display = 'block'
}
}
¿Cómo realizar un test sobre esta función?
Gracias a dos variantes de assert, es muy fácil: assertVisible y assertNotVisible devuelven cierto o falso si el elemento del DOM está oculto o no, respectivamente.
testToggle: function() { with(this) {
$('sandbox').style.display='block';
toggle('sandbox');
assertNotVisible('sandbox');
$('sandbox').style.display='none';
toggle('sandbox');
assertVisible('sandbox');
}}
sandbox es el identificador de un <div> vacío que introducimos en la plantilla HTML generada (el fichero test/javascript/apGeneral_test.html).
Si ejecutamos ahora los tests nos informará de que tenemos 2 tests y 7 aserciones, todas correctas:

Ahora habría que continuar añadiendo tests en el fichero, siempre teniendo en cuenta que:
- las funciones deben de empezar por
test - lo lógico es un test por función que incluya toda la casuística de dicha función (es decir, varios
asserts
Pero ya se sabe qué pasa con los test, que son muy subjetivos, así que no hay reglas de oro, sino experiencia e intentar cubrir toda la funcionalidad que podamos.
Además, por suerte, el Javascript en un proyecto web, en comparación al código del lenguaje servidor será mucho menor, y, posiblemente, más reutilizado. ¡Así que no hay escusa!
