Cómo probar tu código JavaScript con QUnit

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

Que es qunit

QUnit es un potente marco de prueba de unidades de JavaScript que te ayuda a depurar el 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 para probar cualquier código JavaScript regular, e incluso puede probar JavaScript del lado del servidor a través de algún motor JavaScript como Rhino o V8..

Si no está familiarizado con la idea de "pruebas de unidad", no se preocupe. No es demasiado difícil de entender:

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

Esto se cita de Wikipedia. En pocas palabras, usted escribe pruebas para cada funcionalidad de su código, y si todas estas pruebas son aprobadas, puede estar seguro de que el código estará libre de errores (en su mayoría, depende de qué tan exhaustivas sean sus pruebas).

Por qué debería probar su código

Si no ha escrito ninguna prueba de unidad anteriormente, probablemente solo aplique su código a un sitio web directamente, haga clic durante un tiempo para ver si ocurre algún problema e intente solucionarlo cuando lo detecte. Hay muchos problemas con este método..

Primero, es muy tedioso. Hacer clic en realidad no es un trabajo fácil, porque debes 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 hizo 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, corregiste todos los errores que encontraste y lo publicaste. Luego, un usuario envía algunos comentarios sobre nuevos errores y solicita algunas características nuevas. Vuelve al código, corrija estos nuevos errores y agregue estas nuevas características. Lo que podría suceder a continuación es que algunos de los viejos errores vuelven a aparecer, lo que se llama "regresiones". Mira, ahora tienes que hacer clic nuevamente y es probable que no encuentres estos viejos errores de nuevo; incluso si lo hace, tomará un tiempo antes de que descubra que el problema es causado por regresiones. Con las pruebas unitarias, escribe pruebas para encontrar errores, y una vez que se modifica el código, lo filtra a través de las pruebas nuevamente. Si aparece una regresión, algunas pruebas fallarán definitivamente, y usted puede detectarlas fácilmente, sabiendo qué parte del código contiene el error. Ya que sabe lo que acaba de modificar, se puede arreglar fácilmente..

Otra ventaja de las pruebas unitarias es especialmente para el desarrollo web: facilita las pruebas de compatibilidad entre navegadores. Simplemente ejecute sus pruebas en diferentes navegadores, y si ocurre un problema en un navegador, corríjalo y ejecute estas pruebas nuevamente, asegurándose de que no introduzca regresión en otros navegadores. Puede estar seguro de que todos los navegadores de destino son compatibles, una vez que todos pasan las pruebas.

Me gustaría mencionar uno de los proyectos de John Resig: TestSwarm. Lleva las pruebas de unidades de JavaScript a un nuevo nivel, al hacerlas 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 muy rápidamente.

Cómo escribir pruebas unitarias con QUnit

Entonces, ¿cómo escribir pruebas de unidad con QUnit exactamente? Primero, necesita configurar un entorno de prueba:

    QUnit Test Suite         

QUnit Test Suite

    Como puede ver, aquí se utiliza una versión alojada de QUnit framework..

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

    Los bloques de construcción de las pruebas unitarias son afirmaciones..

    Una afirmación es una declaración que predice el resultado de retorno de su código. Si la predicción es falsa, la afirmación ha fallado y usted sabe que algo salió mal..

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

     // Probemos esta función de función isven (val) return val% 2 === 0;  test ('isEven ()', function () ok (isEven (0), 'Zero es un número par'); ok (isEven (2), 'Así que son dos'); ok (isEven (-4) , 'Así son los cuatro negativos'); ok (! IsEven (1), 'Uno no es un número par'); ok (! IsEven (-7), 'Ninguno es siete negativo');)

    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 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 será llamada una vez que se ejecuta QUnit.

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

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

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

    A ver qué pasa si una afirmación ha fallado..

     // Probemos esta función de función isven (val) return val% 2 === 0;  test ('isEven ()', function () ok (isEven (0), 'Zero es un número par'); ok (isEven (2), 'Así que son dos'); ok (isEven (-4) , 'Así son los cuatro negativos'); ok (! IsEven (1), 'One no es un número par'); ok (! IsEven (-7), 'Seven no hace siete'); // Falla ok (isEven (3), 'Tres es un número par');)

    Aquí está el resultado:

    La afirmación ha fallado porque deliberadamente la escribimos mal, pero en su propio proyecto, si la prueba no pasa, y toda la afirmación es correcta, sabe que se ha encontrado un error.

    Más aserciones

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

    Afirmación de comparación

    La aserción de comparación, igual a (), 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 reales y esperados, lo que facilita mucho la depuración. Al igual que ok (), toma un tercer parámetro opcional como mensaje para mostrar.

    Así que en lugar de:

     prueba ('aserciones', función () ok (1 == 1, 'uno es igual a uno');)

    Deberías escribir:

     prueba ('aserciones', función () es igual a (1, 1, 'uno es igual a uno');)

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

    Y si los valores no son iguales:

     prueba ('aserciones', función () es igual a (2, 1, 'uno es igual a uno');)

    Da mucha más información, haciendo la vida mucho más fácil..

    La aserción de comparación usa "==" para comparar sus parámetros, por lo que no maneja la comparación de matriz u objeto:

     prueba ('prueba', función () es igual a (, , 'falla, estos son objetos diferentes'); es igual a (a: 1, a: 1, 'falla'); es igual a ([ ], [], 'falla, hay diferentes matrices'); es igual a ([1], [1], 'falla');)

    Para probar este tipo de igualdad, QUnit proporciona otra aseveración amable: aserción idéntica.

    Afirmacion identica

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

     prueba ('prueba', función () igual (, , 'pasa, los objetos tienen el mismo contenido'); igual (a: 1, a: 1, 'pasa'); igual ( [], [], 'pases, las matrices tienen el mismo contenido'); igual ([1], [1], 'pases');)

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

     prueba ('prueba', función () es igual a (0, falso, 'verdadero'); igual (0, falso, 'falso'); es igual a (nulo, indefinido, 'verdadero'); igual (nulo, no definido, ' falso ');)

    Estructura tus aserciones

    Poner todas las afirmaciones en un solo caso de prueba es una muy mala idea, porque es muy difícil de mantener y no da un resultado limpio. Lo que debe hacer es estructurarlos, colocarlos en diferentes casos de prueba, cada uno con el objetivo de una única funcionalidad..

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

     módulo ('Módulo A'); prueba ('una prueba', función () ); prueba ('otra prueba', función () ); módulo ('Módulo B'); prueba ('una prueba', función () ); prueba ('otra prueba', función () );

    Prueba asincrona

    En ejemplos anteriores, todas las aserciones se llaman de forma síncrona, lo que significa que se ejecutan una tras otra. En el mundo real, también hay muchas funciones asíncronas, 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 asíncrona", que está dedicado a la prueba asíncrona:

    Primero intentemos escribirlo de manera regular:

     prueba ('prueba asíncrona', función () setTimeout (función () ok (verdadero);, 100))

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

    Aquí está la versión correcta:

     prueba ('prueba asíncrona', función () // Detener la prueba primero detener (); setTimeout (función () ok (verdadero); // Después de que se haya llamado a la aserción, // continuar el inicio de la prueba (); , 100))

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

    Llamar a detener () inmediatamente después de llamar a prueba () es bastante común; por lo que QUnit proporciona un acceso directo: asyncTest (). Puedes reescribir el ejemplo anterior así:

     asyncTest ('prueba asíncrona', function () // La prueba se detiene automáticamente setTimeout (function () ok (true); // Después de que se haya llamado a la aserción, // continúe con el inicio de la prueba ();, 100) ))

    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 la función de devolución de llamada será 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:

    Así que aquí está lo que haces:

     // Una función de función personalizada ajax (successCallback) $ .ajax (url: 'server.php', success: successCallback);  prueba ('prueba asíncrona', función () // Pausa la prueba y falla si no se llama a start () después de una parada de segundo (1000); ajax (function () //… inicio de aserciones asíncronas ( );))

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

    ¿Qué hay de múltiples funciones asíncronas? ¿Dónde pones el inicio ()? Lo pones en setTimeout ():

     // Una función de función personalizada ajax (successCallback) $ .ajax (url: 'server.php', success: successCallback);  prueba ('prueba asíncrona', función () // Pausa la parada de prueba (); ajax (función () // ... aserciones asíncronas) ajax (función () // ... aserciones asíncronas) setTimeout (función () inicio ();, 2000);)

    El tiempo de espera debe ser lo suficientemente largo como para permitir que se devuelvan ambas devoluciones de llamada antes de que continúe la prueba. Pero, ¿y si uno de la devolución de llamada no se llama? ¿Cómo puedes saber eso? Aquí es donde entra () en:

     // Una función de función personalizada ajax (successCallback) $ .ajax (url: 'server.php', success: successCallback);  prueba ('prueba asíncrona', función () // Pausa la parada de prueba (); // Le dice a QUnit que espera que se ejecuten tres aserciones expect (3); ajax (function () ok (true);) ajax (function () ok (true); ok (true);) setTimeout (function () start ();, 2000);)

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

    También hay un acceso directo para expect (): solo pasa el número como segundo parámetro para probar () o asyncTest ():

     // Una función de función personalizada ajax (successCallback) $ .ajax (url: 'server.php', success: successCallback);  // Dígale a QUnit que espera tres aserciones para ejecutar la prueba ('prueba asíncrona', 3, función () // Pausa la parada de prueba (); ajax (function () ok (true);) ajax (function () ok (verdadero); ok (verdadero);) setTimeout (function () start ();, 2000);)

    Conclusión

    Eso es todo lo que necesita saber para comenzar con QUnit. La prueba de unidad es un método excelente para probar su código antes de publicarlo. Si no ha escrito ninguna prueba de unidad antes, ¡es hora de comenzar! Gracias por leer!

    • Síganos en Twitter o suscríbase a Nettuts + RSS Feed para obtener los mejores tutoriales de desarrollo web en la web..