+ All Categories
Home > Documents > QUnit CookBook Español

QUnit CookBook Español

Date post: 05-Aug-2015
Category:
Upload: david-rene-comba-lareu
View: 75 times
Download: 1 times
Share this document with a friend
Description:
Todas las funciones basicas para comenzar con el unit testing en javascript.
Popular Tags:
26
Transcript
Page 1: QUnit CookBook Español
Page 2: QUnit CookBook Español

QUnit Cookbook En Español

david rene comba lareu

This book is for sale athttp://leanpub.com/qunit-cookbook-espanol

This version was published on 2012-11-22

This is a Leanpub book. Leanpub helps authors toself-publish in-progress ebooks. We call this idea LeanPublishing.

To learn more about Lean Publishing, go tohttp://leanpub.com/manifesto.

To learn more about Leanpub, go to http://leanpub.com.

©2012 Leanpub

Page 3: QUnit CookBook Español

Tweet This Book!Please help david rene comba lareu by spreading the wordabout this book on Twitter!

The suggested hashtag for this book is #DevNod .

Find out what other people are saying about the book byclicking on this link to search for this hashtag on Twitter:

https://twitter.com/search/#DevNod

Page 4: QUnit CookBook Español

Índice general

Introducción 1

Automatización de unit testing 2

Asserting Results 6

Llamadas de retorno sincronicas 8

Llamadas de retorno asincronicas 10

Testeando acciones de usuario 12

Manteniendo los tests atómicos 15

Agrupando tests 18

Desarrollo Eficiente 20

Page 5: QUnit CookBook Español

IntroducciónEl testeo automático es fundamental en el desarrollo de

software.Unit tests son los bloques básicos para armar testsautomáticos: cada componente, la unidad, del programaes acompañado por un test que puede ser ejecutado porun test runner una y otra vez sin intervención humana.En otras palabras, puedes escribir un test una sola vez yejecutarlo las veces que sean necesarias sin ningún tipo decosto adicional. En adición a los beneficios de una buenacobertura de testeo, esto también puede definir el diseño desoftware, tambien conocido como test-driven design, dondeel test es escrito antes de la implementación. Puedes escribirun test muy simple, verificar que falla (por que el código atestear todavía no existe) y entonces escribir la implemen-tación hasta que pase el test.Una vez que eso sucede, puedesextender el test para cubrir mas funcionalidades deseadase implementar otra vez.Repitiendo estos pasos, el códigoresultante es muy diferente al que se obtiene si se empezarapor la implementación. Unit testing en JavaScript no esmuy diferente de otros lenguajes de programación. Lo quenecesitas es un pequeño framework que provea un entornoejecutor de tests (test runner), ademas de algunas utilidadespara escribir los tests.

1

Page 6: QUnit CookBook Español

Automatización de unittestingProblema

Si quieres automatizar el testeo de tus aplicaciones yframeworks, o tal vez beneficiarse del test-driven design,escribir tu propio testing framework puede ser tentador,pero demanda muchísimo trabajo cubrir todos los detallesy requerimientos especiales de JavaScript para testear elcódigo en varios navegadores.

SoluciónAunque hay otros unit testing frameworks para Ja-

vaScript, has decidido explorar Qunit. Qunit es el unittest framework de jQuery y es usado en una variedad deproyectos. Para usar Qunit, solo debes incluir 2 archivos deQunit en tu pagina HTML. Qunit consiste de qunit.js, elejecutor de tests y test framework y qunit.css, que son losestilos usados para mostrar los resultados de los tests en lapagina.

2

Page 7: QUnit CookBook Español

Automatización de unit testing 3

Abrir este archivo en el navegador da como resultadolo siguiente:

El único código de maquetado necesario en el <body>es un <div> con id=”qunit-fixture”. Esto es necesario paratodos los tests de QUnit, aun cuando el elemento mismoesta vacío. Esto provee el un lugar fijo para los tests, queserá explicado en la sección llamada “Manteniendo los testsatómicos”.

La parte interesante es el elemento *

Page 8: QUnit CookBook Español

Automatización de unit testing 4

DiscusiónEl encabezado de la test suite muestra el titulo de la

pagina, una barra verde cuando todos los tests han pasado(una barra roja se muestra cuando alguno de ellos hafallado), una barra con unos checkboxes para filtrar losresultados y una barra azul con el navegador, el userAgent(muy util para sacar capturas de pantalla de los resultadosen diferentes navegadores). De los checboxes, “Hide passedtests” es útil cuando se ejecutanmuchos tests y solo algunoshan fallado. Tildando la caja, se van a esconder todos lostests que hallan pasado, haciendo mas fácil el enfocarseen aquellos que fallaron (esto se explica en detalle en lasección “Desarrollo eficiente”). Tildar “Check for globals”causa que QUnit haga una lista de todas las propiedadesdel objeto ventana (window object) antes y después de cadatest, y chequear las diferencias después de cada uno.Estoayuda a estar seguro de que tu código de testeo y elcódigo dentro de este, no exporte ninguna propiedad alámbito global. El “No try-catch” checkbox le dice a QUnitde probar el código por fuera de un bloque try-catch.Cuando el código tire una excepción, el ejecutor de testsmorirá. siendo incapaz de continuar pero se consigue comoresultado una excepción “nativa”, que puede ser de granayuda en navegadores viejos donde el soporte paramanejarexcepciones es deficiente (como en internet explorer 6).Debajo de la cabecera esta el sumario, mostrando el tiempototal que tomo ejecutar todos los tests como también el totalde tests que han pasado y fallado. Mientras todavía existantests que se estén ejecutando, se mostraran sus nombres.

Page 9: QUnit CookBook Español

Automatización de unit testing 5

El contenido actual de la pagina van a ser los resultados delos tests, cada entrada en la lista empieza con el nombre deltest, seguido por, en paréntesis, el numero de tests que hanpasado, que han fallado y el numero total de assertions.Clickeando cada entrada va a mostrar los resultados decada assertion, usualmente con detalles sobre el resultadoesperado y el obtenido. El link “Rerun” al fondo de cada testse usa para re-ejecutar ese test únicamente.

Page 10: QUnit CookBook Español

Asserting ResultsProblema

Un elemento esencial de cualquier unit test son lasassertions. El autor del test debe expresar el resultadoesperado y hacer que el unit testing framework lo comparecon lo valores que la implementación produce.

SoluciónQUnit provee de 3 assertions.ok( truthy [, message ] )El mas básico es ok() que solo requiere de 1 argumento.

Si la evaluación del argumento resulta positiva (true) laassertion pasa, si en cambio resulta con otro resultado, falla.También acepta como parámetro opcional un texto paramostrar en los resultados del test:

equal( actual, expected [, message ] )La assertion equal usa el operador simple de compa-

ración (==) para comparar los resultados actuales con losesperados. Cuando son iguales, la assertion pasa, de otramanera, falla. Cuando falla, tanto el resultado esperado

6

Page 11: QUnit CookBook Español

Asserting Results 7

com el recibido son mostrados en los resultados del test,ademas del mensaje suministrado como tercer argumento.

![]images/img4.jpg)Comparado con ok(), equal() hace mucho mas fácil

depurar tests que han fallado, por que es obvio que valorcauso que el test fallara.Si fuera necesario una comparaciónestricta (==), se puede usar strictEqual().

deepEqual( actual, expected [, message ] )La assertion deepEqual() puede usarse como equal() y

es la mejor opción en la mayoría de las ocasiones. En vez deusar el operador de comparación simple (==), este usa unoperador mas especifico (===). De esta forma, undefinedno equivale a null, 0 o una cadena vacía (“ “). Tambiéncompara el contenido de los objetos, así {key: value} esigual a {key: value} cuando se comparan 2 objetos conidentidades diferentes. deepEqual() también maneja NaN,dates, expresiones regulares, arrays, y funciones, mientrasequal() solo chequea la identidad del objeto:

En el caso de que explícitamente no se quiera compararel contenido de 2 valores, todavía puede usarse equal(). Engeneral, deepEqual(), es la mejor opción.

Page 12: QUnit CookBook Español

Llamadas de retornosincronicasProblema

Ocasionalmente, diferentes circunstancias en tu códigopuede provocar que las assertions nunca sean llamadas,causando de que el test falle silenciosamente.

SoluciónQUnit provee una assertion especial para definir la

cantidad de assertions que contiene un test. Cuando el testse completa sin el numero adecuado de assertions, estefallará, sin importar el resultado de los otros assertions. Eluso es muy simple, solamente llama a expect() a principiodel test, con el numero de assertions esperadas como únicoargumento:

Opcionalmente, la cantidad de assertions esperadaspuede pasarse como segundo parámetro de test():

8

Page 13: QUnit CookBook Español

Llamadas de retorno sincronicas 9

Ejemplo practico:

Discusionexpect() provee de la mayor herramienta al probar

llamadas de retorno. Cuando todo el código corre en elmarco de la función de test, expect() no provee ningún valoradicional - cualquier error que no permita las assertionsejecutarse, va a causar que el test falle, por que el ejecutorde tests captura el error y hace fallar la unidad.

Page 14: QUnit CookBook Español

Llamadas de retornoasincronicasProblema

Mientras que expect() es util para probar código sin-crónico, este falla cuando existe código asincrónico. Códigoasincrónico entra en conflicto en la forma que el ejecutorde tests lo pone en una cola de ejecución y ejecuta los tests.Cuando el código dentro del test framework comienza untimeout, un interval o un ajax request, el ejecutor del test vaa continuar con el resto del test, y todos los otros test quele sigan, en vez de esperar por el resultado de la funciónasincrónica.

SoluciónEn vez de envolver las assertions en un test(), debe

usarse asyncTest() y llamar a start() cuando el bloque detesteo esta completo y listo para resumir:

Ejemplo practico:

10

Page 15: QUnit CookBook Español

Llamadas de retorno asincronicas 11

Page 16: QUnit CookBook Español

Testeando acciones deusuarioProblemas

Código que depende de acciones iniciadas por el usua-rio no pueden ser testeadas simplemente llamando a unafunción. Usualmente una función anónima esta adheridaa un evento de un elemento Ej: un click, que debe sersimulado.

SoluciónPuedes disparar el evento usando la función de jQuery

trigger() y probar que se produzca el comportamiento espe-rado. Si no quieres que eventos nativos del navegador seandisparados, puedes usar triggerHandler() para solo ejecutarlos event handlers. Esto es útil cuando se testea un evento declick, donde trigger() va a causar que el navegador cambiede locación, que es difícilmente lo que se quiere en un test.Asumamos que tenemos un simple registrador de teclas quequeremos probar:

12

Page 17: QUnit CookBook Español

Testeando acciones de usuario 13

Podemos manualmente disparar el evento keypresspara ver si el registrador esta funcionando:

DiscusiónSi tu manejador de evento no depende de ninguna pro-

piedad especifica del evento, puede simplemente llamar a.trigger(eventType). Sin embargo, si tu manejador dependede alguna propiedad especifica del evento, es necesariocrear un objeto de evento usando $.Event y setear las pro-piedades necesarias, como fue mostrado anteriormente. Estambien importante disparar todos los eventos relevantespara comportamientos complejos como el arrastre, querequiere de unmousedown, por lo menos de unmousemovey un mouseup . Hay que tener presente que algunos testsque parecen simples, son en realidad, complejos Ej: un clickes en realidad un mousedown, un mouseup y un click. Siverdaderamente es necesario disparar todos estos eventosdepende del código que este bajo testeo. Disparar solamenteun click es suficiente en la mayoría de los casos. Si eso noes suficiente, existen unas cuantas opciones en frameworks

Page 18: QUnit CookBook Español

Testeando acciones de usuario 14

para simular eventos del usuario:*syn: “Es una librería sintética de eventos que bá-

sicamente maneja tipeo, clickeo, movimiento, y arrastreexactamente como un usuario real haría esas acciones”.Usada por FuncUnit, que esta basado en QUnit, para testeofuncional de aplicaciones web. *JSRobot: “Una herramien-ta de testeo para aplicaciones web que puede generarkeystrokes reales mas que simplemente simular el disparode eventos en Javascript. Esto habilita a que se disparencomportamientos inherentes en el navegador que de otramanera no seria posible. *“DOH Robot” provee una APIque permite a los testers automatizar los UI tests usandoreal, cross-platform, inputs a nivel sistema.Esto te permiteestar lo mas cerca posible de eventos “reales” de navegador,pero usa java applets para generar esto.

Page 19: QUnit CookBook Español

Manteniendo los testsatómicosProblema

Cuando los tests son puestos juntos, es posible tenertests que deberían pasar pero fallan o tests que deberíanfallar pero pasan. Esto es resultado de tests teniendo resul-tados inválidos por efectos secundarios de tests anteriores:

El primer append() añade un <div> que el segundoequal() no toma en consideración.

SoluciónUsa el método test() para mantener los tests atómicos,

siendo cuidadoso de mantener cada assertion limpia decualquier efecto secundario. Debes solo depender en unmaquetado fijo, dentro del elemento #qunit-fixture. Modi-ficando y dependiendo de cualquier otra cosa puede tenerefectos secundarios:

15

Page 20: QUnit CookBook Español

Manteniendo los tests atómicos 16

QUnit va a resetear los elementos dentro de #qunit-fixture después de cada test, eliminando cualquier eventoque existiera. Si usas solo elementos con esta estructura,no necesitas limpiar manualmente para mantener los testsatómicos.

DiscusiónEn adición a #qunit-fixture y los filtros explicados en

la sección llamada “Desarrollo Eficiente”, QUnit tambiénofrece un parámetro llamado ?noglobals como en el si-guiente ejemplo:

En un test normal, esto pasaría como un resultadovalido. Correr el ok() con el parámetro noglobals causaque el test falle, por que QUnit detecta que ha populadoel objeto window. No es necesario usar este parámetro

Page 21: QUnit CookBook Español

Manteniendo los tests atómicos 17

todo el tiempo, pero puede ser útil para detectar polucióndentro del namespace global que puede ser problemáticoen combinación con librerías de terceros. También ayuda adetectar bugs en tests causados por efectos secundarios.

Page 22: QUnit CookBook Español

Agrupando testsProblema

Has separado todos tus tests paramantenerlos atómicosy libre de efectos secundarios, pero quieres mantenerloslógicamente organizados y ser capaz de correr un grupoespecíficos de tests por si solo.

SoluciónPuedes usar la función module() para agrupar tests:

El test que ocurre después de la llamada a module() vaa ser agrupada en ese modulo. El nombre de los tests vaa preceder por el nombre del modulo en los resultados deltest. Puedes usar ese nombre de modulo para seleccionarlos tests a ejecutar (mira la sección “Desarrollo Eficiente”).

DiscusiónAdemas de agrupar tests,module() puede ser usado pa-

ra extraer código en común de tests que estén en el mismo

18

Page 23: QUnit CookBook Español

Agrupando tests 19

modulo. La función module() usa el segundo parámetroopcional para definir las funciones a correr antes y despuésde cada test dentro de ese modulo:

Puedes especificar el parámetro setup o teardown olos 2.Llamar a module() otra vez sin ningún argumentoadicional va a simplemente resetear cualquier propiedadsetup/teardown definida anteriormente en otro modulo.

Page 24: QUnit CookBook Español

Desarrollo EficienteProblema

Una vez que tu set de tests tardamas que unos segundosen correr, quieres evadir perder un montón de tiempoesperando los resultados.

SoluciónQUnit tiene muchas características que puede solu-

cionar eso.La mas interesante solo requiere de un clickpara ser activada. Clickea el ítem “Hide passed tests” alprincipio de la pagina y QUnit solo va a mostrar los testsque fallaron. Eso solo no hace diferencia en velocidad,pero ayuda a concentrarse en los tests que fallan. Se ponemas interesante si se toma en cuenta otra característica deQUnit, que esta habilitada por default y normalmente no senota. Cualquier test que falla, QUnit guarda el nombre deltest en sessionStorage. La próxima vez que corras la seriede tests, ese test que fallaba va a correr antes que todos losotros tests. El orden de salida no es afectado, solo el ordende ejecución. En combinación con “Hide passed tests” vasa poder ver el test que fallo al principio y lo antes posible.

DiscusiónEl re-ordenado automático sucede por default. Esto

implica que tus tests deben ser atómicos, como se discutiópreviamente. Si tus tests no lo son, vas a obtener erroresaleatorios. Arreglar esto es usualmente la mejor opción,

20

Page 25: QUnit CookBook Español

Desarrollo Eficiente 21

pero si estas verdaderamente desesperado, se puede setearQUnit.config.reorder = false. Ademas del re-ordenamientoautomático, hay algunas opciones manuales disponibles.Puedes volver a ejecutar cualquier test clickeando “Rerun”en cualquier test. Eso va a agregar un “testNumber=N”parámetro a la url del test, donde N es el numero de test queclickeaste. Puedes recargar la pagina para seguir corriendoese test o usar el botón “Atrás” del navegador para volvera ejecutar todos los tests. Correr todos los tests con unmodulo funciona de la misma manera, solo que eliges elmodulo a correr desde el selector al principio de la paginaa la derecha. Va a setear un “module=N” en la url, donde Nes el nombre encodeado del modulo.

ConclusionEsta es una introduccion basica a QUnit, con las funcio-

nes mas importantes y mas usadas de este test framework.El contenido de este libro fue traducido al español a partirde lo publicado en la pagina de QUnit bajo la seccion “Co-okBook” (http://qunitjs.com/cookbook/¹) por las siguientespersonas y con la siguiente licencia:

This section was first published, under a non-exclusivelicense, as the last chapter in the jQuery Cookbook, autho-red by Scott González and Jörn Zaefferer. As QUnit chan-ged since the book was printed, this version is more up-to-date. This work is licensed under a Creative CommonsAttribution 3.0 Unported License.

¹http://qunitjs.com/cookbook/

Page 26: QUnit CookBook Español

Desarrollo Eficiente 22

Como la version original, esta traduccion posee lamisma licencia anteriormente mencionada.

La traduccion fue echa por David Rene Comba Lareu,para DevNod.com (http://www.devnod.com²) con la unicaintencion de brindar material tecnico en español.

²http://www.devnod.com


Recommended