Qunit CookBook español

782 views

Published on

Aprende las bases del unit testing en Javascript con este CookBook de QUnit - Traducido para DevNod.com

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
782
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
20
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Qunit CookBook español

  1. 1. QUnit Cookbook En Españoldavid rene comba lareuThis book is for sale athttp://leanpub.com/qunit-cookbook-espanolThis version was published on 2012-11-22This 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
  2. 2. 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
  3. 3. Índice generalIntroducción 1Automatización de unit testing 2Asserting Results 6Llamadas de retorno sincronicas 8Llamadas de retorno asincronicas 10Testeando acciones de usuario 12Manteniendo los tests atómicos 15Agrupando tests 18Desarrollo Eficiente 20
  4. 4. Introducción El testeo automático es fundamental en el desarrollo desoftware. 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
  5. 5. 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ón Aunque 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
  6. 6. 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 *
  7. 7. Automatización de unit testing 4Discusión El encabezado de la test suite muestra el titulo de lapagina, 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 ejecutan muchos 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 para manejarexcepciones 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.
  8. 8. Automatización de unit testing 5El 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.
  9. 9. 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ón QUnit 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
  10. 10. Asserting Results 7com 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ácildepurar 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() yes 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.
  11. 11. 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ón QUnit provee una assertion especial para definir lacantidad 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
  12. 12. Llamadas de retorno sincronicas 9 Ejemplo practico:Discusion expect() provee de la mayor herramienta al probarllamadas 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.
  13. 13. 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ón En vez de envolver las assertions en un test(), debeusarse asyncTest() y llamar a start() cuando el bloque detesteo esta completo y listo para resumir: Ejemplo practico: 10
  14. 14. Llamadas de retorno asincronicas 11
  15. 15. 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ón Puedes disparar el evento usando la función de jQuerytrigger() 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
  16. 16. Testeando acciones de usuario 13 Podemos manualmente disparar el evento keypresspara ver si el registrador esta funcionando:Discusión Si 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 un mousedown, por lo menos de un mousemovey 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
  17. 17. Testeando acciones de usuario 14para 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.
  18. 18. 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ón Usa 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
  19. 19. 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ón En adición a #qunit-fixture y los filtros explicados enla 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
  20. 20. Manteniendo los tests atómicos 17todo 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.
  21. 21. Agrupando testsProblema Has separado todos tus tests para mantenerlos 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ón Puedes 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ón Ademas de agrupar tests, module() puede ser usado pa-ra extraer código en común de tests que estén en el mismo 18
  22. 22. Agrupando tests 19modulo. 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.
  23. 23. Desarrollo EficienteProblema Una vez que tu set de tests tarda mas que unos segundosen correr, quieres evadir perder un montón de tiempoesperando los resultados.Solución QUnit 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ón El re-ordenado automático sucede por default. Estoimplica 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
  24. 24. Desarrollo Eficiente 21pero 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.Conclusion Esta 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/
  25. 25. 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

×