Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development

Cómo probar tu código JavaScript con QUnit

by
Read Time:11 minsLanguages:

Spanish (Español) translation by Marjan (you can also view the original English article)

QUnit, desarrollado por el equipo de jQuery, es un gran marco para la prueba unitaria de JavaScript. En este tutorial, presentaré qué es QUnit específicamente y por qué deberías preocuparte por probar rigurosamente tu código.

Qué es QUnit

QUnit es un potente marco de pruebas unitarias de JavaScript que te ayuda a depurar código. Está escrito por miembros del equipo de jQuery y es el conjunto de pruebas oficial de jQuery.  Pero QUnit es lo suficientemente general como para probar cualquier código JavaScript normal, e incluso puedes probar JavaScript del lado del servidor a través de algún motor JavaScript como Rhino o V8.

Si no estás familiarizado con la idea de "pruebas unitarias", no te preocupes. No es demasiado difícil de entender:

En la programación de computadoras, las pruebas unitarias son un método de verificación y validación de software en el que un programador prueba si las unidades individuales de código fuente son aptas para su uso. Una unidad es la parte comprobable más pequeña de una aplicación. En la programación de procedimientos, una unidad puede ser una función o procedimiento individual.

Esto se cita de Wikipedia. En pocas palabras, escribe pruebas para cada funcionalidad de tu código, y si se pasan todas estas pruebas, puedes estar seguro de que el código estará libre de errores (principalmente, depende de cuán exhaustivas sean tus pruebas).

Por qué deberías probar tu código

Si no has escrito ninguna prueba unitaria antes, probablemente solo aplicas tu código a un sitio web directamente, haces clic durante un tiempo para ver si ocurre algún problema e intentas solucionarlo cuando detectas uno. Hay muchos problemas con este método.

Primero, es muy tedioso. Hacer clic en realidad no es un trabajo fácil, porque tienes que asegurarte de que se haga clic en todo y es muy probable que te pierdas una o dos cosas. En segundo lugar, todo lo que hiciste para las pruebas no es reutilizable, lo que significa que no es fácil encontrar regresiones. ¿Qué es una regresión? Imagina que escribiste un código y lo probaste, corrigiste todos los errores que encontraste y lo publicaste. Luego, un usuario envía algunos comentarios sobre nuevos errores y solicita algunas funciones nuevas. Vuelves al código, corriges estos nuevos errores y agregas estas nuevas funciones.  Lo que podría suceder a continuación es que vuelvan a aparecer algunos de los errores antiguos, que se denominan "regresiones". Mira, ahora tienes que hacer clic de nuevo, y es probable que no vuelvas a encontrar estos viejos errores; incluso si lo haces, pasará un tiempo antes de que te des cuenta de que el problema es causado por regresiones. Con las pruebas unitarias, escribes pruebas para encontrar errores y, una vez que se modifica el código, lo vuelves a filtrar a través de las pruebas. Si aparece una regresión, algunas pruebas definitivamente fallarán, y puedes detectarlas fácilmente, sabiendo qué parte del código contiene el error. Como sabes lo que acabas de modificar, puedes solucionarlo fácilmente.

Otra ventaja de las pruebas unitarias es especialmente para el desarrollo web: facilita las pruebas de compatibilidad entre navegadores. Simplemente ejecuta tus pruebas en diferentes navegadores, y si ocurre un problema en un navegador, lo corriges y ejecutas estas pruebas nuevamente, asegurándote de que no introduce regresión en otros navegadores. Puedes estar seguro de que todos los navegadores de destino son compatibles, una vez que pasen las pruebas.

Me gustaría mencionar uno de los proyectos de John Resig: TestSwarm. Lleva las pruebas unitarias de JavaScript a un nuevo nivel, haciéndolas distribuidas. Es un sitio web que contiene muchas pruebas, cualquiera puede ir allí, ejecutar algunas de las pruebas y luego devolver el resultado al servidor. De esta manera, el código se puede probar en diferentes navegadores e incluso en diferentes plataformas con mucha rapidez.

Cómo escribir pruebas unitarias con QUnit

Entonces, ¿cómo se escriben las pruebas unitarias con QUnit exactamente? Primero, necesitas configurar un entorno de prueba:

Como puedes ver, aquí se utiliza una versión alojada del marco QUnit.

El código que se va a probar debe colocarse en myProject.js y tus pruebas deben insertarse en myTests.js. Para ejecutar estas pruebas, simplemente abre este archivo HTML en un navegador. Ahora es el momento de escribir algunas pruebas.

Los componentes básicos de las pruebas unitarias son las afirmaciones.

Una afirmación es una declaración que predice el resultado de devolución de tu código. Si la predicción es falsa, la afirmación ha fallado y sabes que algo salió mal.

Para ejecutar afirmaciones, debes ponerlas en un caso de prueba:

Aquí definimos una función, isEven, que detecta si un número es par, y queremos probar esta función para asegurarnos de que no devuelva respuestas incorrectas.

Primero llamamos a test(), que construye un caso de prueba; el primer parámetro es una cadena que se mostrará en el resultado, y el segundo parámetro es una función de devolución de llamada que contiene nuestras afirmaciones. Esta función de devolución de llamada se llamará una vez que se ejecute QUnit.

Escribimos cinco afirmaciones, todas booleanas. Una afirmación booleana espera que su primer parámetro sea verdadero. El segundo parámetro también es un mensaje que se mostrará en el resultado.

Esto es lo que obtienes, una vez que ejecutas la prueba:

a test for isEven()a test for isEven()a test for isEven()

Dado que todas estas afirmaciones han pasado con éxito, podemos estar bastante seguros de que isEven() funcionará como se esperaba.

Veamos qué sucede si falla una afirmación.

Aquí está el resultado:

a test contains failed assertion for isEven()a test contains failed assertion for isEven()a test contains failed assertion for isEven()

La afirmación ha fallado porque deliberadamente la escribimos mal, pero en tu propio proyecto, si la prueba no pasa y todas las afirmaciones son correctas, sabrás que se ha encontrado un error.

Más afirmaciones

ok() no es la única afirmación que proporciona QUnit. Hay otros tipos de afirmaciones que son útiles al probar tu proyecto:

Afirmación de comparación

La afirmación de comparación, equals(), espera que su primer parámetro (que es el valor real) sea igual a su segundo parámetro (que es el valor esperado). Es similar a ok(), pero genera valores tanto reales como esperados, lo que hace que la depuración sea mucho más fácil. Al igual que ok(), toma un tercer parámetro opcional como mensaje que se mostrará.

Entonces en lugar de:

a boolean assertiona boolean assertiona boolean assertion

Deberías escribir:

a comparison assertiona comparison assertiona comparison assertion

Observa el último "1", que es el valor de comparación.

Y si los valores no son iguales:

a failed comparison assertiona failed comparison assertiona failed comparison assertion

Brinda mucha más información, lo que hace la vida mucho más fácil.

La afirmación de comparación usa "==" para comparar sus parámetros, por lo que no maneja la comparación de matrices u objetos:

Para probar este tipo de igualdad, QUnit proporciona otro tipo de afirmación: afirmación idéntica.

Afirmación idéntica

La afirmación idéntica, same(), espera los mismos parámetros que equals(), pero es una afirmación de comparación recursiva profunda que funciona no solo en tipos primitivos, sino también en matrices y objetos. Las afirmaciones, en el ejemplo anterior, pasarán todas si las cambias a afirmaciones idénticas:

Ten en cuenta que same() usa '===' para hacer una comparación cuando sea posible, por lo que será útil al comparar valores especiales:

Estructura tus afirmaciones

Poner todas las afirmaciones en un solo caso de prueba es una muy mala idea, porque es muy difícil de mantener y no devuelve un resultado limpio. Lo que debes hacer es estructurarlas, colocarlas en diferentes casos de prueba, cada una con el objetivo de una sola funcionalidad.

Incluso puedes organizar casos de prueba en diferentes módulos llamando a la función del módulo:

structure assertionsstructure assertionsstructure assertions

Prueba asincrónica

En los ejemplos anteriores, todas las afirmaciónes se llaman sincrónicamente, lo que significa que se ejecutan una tras otra. En el mundo real, también hay muchas funciones asincrónicas, como llamadas ajax o funciones llamadas por setTimeout() y setInterval(). ¿Cómo podemos probar este tipo de funciones? QUnit proporciona un tipo especial de caso de prueba llamado "prueba asincrónica", que se dedica a las pruebas asincrónicas:

Primero intentemos escribirlo de manera regular:

an incorrent example of asychronous testan incorrent example of asychronous testan incorrent example of asychronous test

¿Ves? Es como si no hubiéramos escrito ninguna afirmación. Esto se debe a que la afirmación se ejecutó de forma asincrónica, cuando se llamó, el caso de prueba ya había finalizado.

Aquí está la versión correcta:

a correct example of asychronous testa correct example of asychronous testa correct example of asychronous test

Aquí, usamos stop() para pausar el caso de prueba, y después de que se haya llamado a la afirmación, usamos start() para continuar.

Llamar a stop() inmediatamente después de llamar a test() es bastante común; por lo que QUnit proporciona un atajo: asyncTest(). Puedes reescribir el ejemplo anterior de esta manera:

Hay una cosa a tener en cuenta: setTimeout() siempre llamará a su función de devolución de llamada, pero ¿qué pasa si es una función personalizada (por ejemplo, una llamada ajax)? ¿Cómo puedes estar seguro de que se llamará a la función de devolución de llamada? Y si no se llama a la devolución de llamada, no se llamará a start() y se bloqueará toda la prueba de la unidad:

unit testing hangsunit testing hangsunit testing hangs

Así que esto es lo que haces:

Pasas un tiempo de espera a stop(), que le dice a QUnit, "si no se llama a start() después de ese tiempo de espera, deberías fallar esta prueba". Puedes estar seguro de que toda la prueba no se bloqueará y se te notificará si algo sale mal.

¿Qué hay de múltiples funciones asincrónicas? ¿Dónde pones el start()? Lo pones en setTimeout():

El tiempo de espera debe ser lo suficientemente largo para permitir que se invoquen ambas devoluciones de llamada antes de que continúe la prueba. Pero, ¿qué pasa si no se llama a una de las devoluciones de llamada? ¿Cómo puedes saber eso? Aquí es donde entra la expect():

Pasas un número para expect() para decirle a QUnit que esperas que se ejecuten X afirmaciones, si no se llama una de las afirmaciones, el número no coincidirá y se te notificará que algo salió mal.

También hay un atajo para expect(): simplemente pasa el número como segundo parámetro para test() o asyncTest():

Conclusión

Eso es todo lo que necesitas saber para comenzar con QUnit. Las pruebas unitarias son un gran método para probar tu código antes de publicarlo. Si no has escrito ninguna prueba unitaria antes, ¡es hora de comenzar! ¡Gracias por leer!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.