Introducción a las pruebas unitarias de JavaScript

 

 

 

  • SmashingConf UX Design, Antwerp 2024
  • Design Patterns For AI Interfaces, with Vitaly Friedman

  • Índice
    1. Lecturas adicionales sobre SmashingMag:
    2. Pruebas unitarias de construcción
    3. Hacer que las cosas sean comprobables
    4. Refactorización, etapa 0
    5. El conjunto de pruebas de JavaScript QUnit
    6. Refactorización, etapa 1
    7. Probando la manipulación DOM
    8. Refactorización, etapa 2
    9. De vuelta al principio
    10. Conclusión

    Probablemente sepa que las pruebas son buenas, pero el primer obstáculo que debe superar al intentar escribir pruebas unitarias para código del lado del cliente es la falta de unidades reales; El código JavaScript se escribe para cada página de un sitio web o cada módulo de una aplicación y está estrechamente entremezclado con la lógica de back-end y el HTML relacionado. En el peor de los casos, el código está completamente mezclado con HTML, como controladores de eventos en línea.

     

    Probablemente sepa que las pruebas son buenas, pero el primer obstáculo que debe superar al intentar escribir pruebas unitarias para código del lado del cliente es la falta de unidades reales; El código JavaScript se escribe para cada página de un sitio web o cada módulo de una aplicación y está estrechamente entremezclado con la lógica de back-end y el HTML relacionado. En el peor de los casos, el código está completamente mezclado con HTML, como controladores de eventos en línea.

    Este es probablemente el caso cuando no se utiliza ninguna biblioteca JavaScript para alguna abstracción DOM; escribir controladores de eventos en línea es mucho más fácil que usar las API DOM para vincular esos eventos. Cada vez más desarrolladores eligen una biblioteca como jQuery para manejar la abstracción DOM, lo que les permite mover esos eventos en línea a scripts distintos, ya sea en la misma página o incluso en un archivo JavaScript separado. Sin embargo, poner el código en archivos separados no significa que esté listo para ser probado como una unidad.

    Lecturas adicionales sobre SmashingMag:

    • Escribir JavaScript rápido y con memoria eficiente
    • Errores de JavaScript que se deben evitar con un analizador de código estático
    • Análisis de las características de la red utilizando JavaScript y DOM
    • Encuentre la solución JavaScript adecuada con una prueba de 7 pasos

    ¿Qué es una unidad de todos modos? En el mejor de los casos, es una función pura con la que puedes lidiar de alguna manera: una función que siempre te da el mismo resultado para una entrada determinada. Esto hace que las pruebas unitarias sean bastante fáciles, pero la mayoría de las veces es necesario lidiar con los efectos secundarios, lo que aquí significa manipulaciones DOM. Sigue siendo útil determinar en qué unidades podemos estructurar nuestro código y crear pruebas unitarias en consecuencia.

     

    Pruebas unitarias de construcción

    Teniendo esto en cuenta, obviamente podemos decir que comenzar con pruebas unitarias es mucho más fácil cuando se comienza algo desde cero. Pero de eso no se trata este artículo. Este artículo tiene como objetivo ayudarle con el problema más difícil: extraer el código existente y probar las partes importantes, potencialmente descubriendo y corrigiendo errores en el código.

    El proceso de extraer código y ponerlo en una forma diferente, sin modificar su comportamiento actual, se llama refactorización. La refactorización es un método excelente para mejorar el diseño del código de un programa; y debido a que cualquier cambio podría modificar el comportamiento del programa, es más seguro hacerlo cuando existen pruebas unitarias.

    Este problema del huevo y la gallina significa que para agregar pruebas al código existente, debes correr el riesgo de romper cosas. Por lo tanto, hasta que tenga una cobertura sólida con pruebas unitarias, debe continuar realizando pruebas manualmente para minimizar ese riesgo.

    Esto debería ser suficiente teoría por ahora. Veamos un ejemplo práctico, probando algún código JavaScript que actualmente está mezclado y conectado a una página. El código busca enlaces con titleatributos y utiliza esos títulos para mostrar cuándo se publicó algo, como un valor de tiempo relativo, como "hace 5 días":

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleMangled date examples/title script function prettyDate(time){ var date = new Date(time || ""), diff = ((new Date().getTime() - date.getTime()) / 1000), day_diff = Math.floor(diff / 86400); if (isNaN(day_diff) || day_diff 0 || day_diff = 31) { return; } return day_diff == 0 ( diff 60 "just now" || diff 120 "1 minute ago" || diff 3600 Math.floor( diff / 60 ) + " minutes ago" || diff 7200 "1 hour ago" || diff 86400 Math.floor( diff / 3600 ) + " hours ago") || day_diff == 1 "Yesterday" || day_diff 7 day_diff + " days ago" || day_diff 31 Math.ceil( day_diff / 7 ) + " weeks ago"; } window.onload = function(){ var links = document.getElementsByTagName("a"); for (var i = 0; i links.length; i++) { if (links[i].title) { var date = prettyDate(links[i].title); if (date) { links[i].innerHTML = date; } } } }; /script/headbodyulli pblah blah blah…/p small Posted a href="/2008/01/blah/57/"January 28th, 2008/a by a href="/john/"John Resig/a /small/li!-- more list items --/ul/body/html

    Si ejecutara ese ejemplo, vería un problema: ninguna de las fechas se reemplaza. Sin embargo, el código funciona. Recorre todos los anclajes de la página y busca una titlepropiedad en cada uno. Si hay uno, lo pasa a la prettyDatefunción. Si prettyDatedevuelve un resultado, actualiza el innerHTMLenlace con el resultado.

     

    Hacer que las cosas sean comprobables

    El problema es que para cualquier fecha mayor a 31 días, prettyDatesimplemente devuelve indefinido (implícitamente, con una sola returndeclaración), dejando el texto del ancla como está. Entonces, para ver qué se supone que sucede, podemos codificar una fecha "actual":

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleMangled date examples/title script function prettyDate(now, time){ var date = new Date(time || ""), diff = (((new Date(now)).getTime() - date.getTime()) / 1000), day_diff = Math.floor(diff / 86400); if (isNaN(day_diff) || day_diff 0 || day_diff = 31) { return; } return day_diff == 0 ( diff 60 "just now" || diff 120 "1 minute ago" || diff 3600 Math.floor( diff / 60 ) + " minutes ago" || diff 7200 "1 hour ago" || diff 86400 Math.floor( diff / 3600 ) + " hours ago") || day_diff == 1 "Yesterday" || day_diff 7 day_diff + " days ago" || day_diff 31 Math.ceil( day_diff / 7 ) + " weeks ago"; } window.onload = function(){ var links = document.getElementsByTagName("a"); for (var i = 0; i links.length; i++) { if (links[i].title) { var date = prettyDate("2008-01-28T22:25:00Z", links[i].title); if (date) { links[i].innerHTML = date; } } } }; /script/headbodyulli pblah blah blah…/p small Posted a href="/2008/01/blah/57/"January 28th, 2008/a by a href="/john/"John Resig/a /small/li!-- more list items --/ul/body/html
    • Ejecute este ejemplo.

    Ahora, los enlaces deberían decir "Hace 2 horas", "Ayer", etc. Eso es algo, pero todavía no es una unidad comprobable real. Entonces, sin cambiar más el código, todo lo que podemos hacer es intentar probar los cambios DOM resultantes. Incluso si eso funcionara, cualquier pequeño cambio en el margen probablemente rompería la prueba, lo que resultaría en una relación costo-beneficio realmente mala para una prueba como esa.

     

    Refactorización, etapa 0

    En su lugar, refactoricemos el código lo suficiente como para tener algo que podamos probar unitariamente.

    Necesitamos hacer dos cambios para que esto suceda: pasar la fecha actual a la prettyDatefunción como argumento, en lugar de usarla simplemente new Date, y extraer la función a un archivo separado para que podamos incluir el código en una página separada para la unidad. pruebas.

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleRefactored date examples/title script src="prettydate.js"/script script window.onload = function() { var links = document.getElementsByTagName("a"); for ( var i = 0; i links.length; i++ ) { if (links[i].title) { var date = prettyDate("2008-01-28T22:25:00Z", links[i].title); if (date) { links[i].innerHTML = date; } } } }; /script/headbodyulli pblah blah blah…/p small Posted a href="/2008/01/blah/57/"January 28th, 2008/a by a href="/john/"John Resig/a /small/li!-- more list items --/ul/body/html

    Aquí está el contenido de prettydate.js:

    function prettyDate(now, time){ var date = new Date(time || ""), diff = (((new Date(now)).getTime() - date.getTime()) / 1000), day_diff = Math.floor(diff / 86400); if (isNaN(day_diff) || day_diff 0 || day_diff = 31) { return; } return day_diff == 0 ( diff 60 "just now" || diff 120 "1 minute ago" || diff 3600 Math.floor( diff / 60 ) + " minutes ago" || diff 7200 "1 hour ago" || diff 86400 Math.floor( diff / 3600 ) + " hours ago") || day_diff == 1 "Yesterday" || day_diff 7 day_diff + " days ago" || day_diff 31 Math.ceil( day_diff / 7 ) + " weeks ago";}
    • Ejecute este ejemplo.

    Ahora que tenemos algo que probar, escribamos algunas pruebas unitarias reales:

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleRefactored date examples/title script src="prettydate.js"/script script function test(then, expected) { results.total++; var result = prettyDate("2008-01-28T22:25:00Z", then); if (result !== expected) { results.bad++; console.log("Expected " + expected + ", but was " + result); } } var results = { total: 0, bad: 0 }; test("2008/01/28 22:24:30", "just now"); test("2008/01/28 22:23:30", "1 minute ago"); test("2008/01/28 21:23:30", "1 hour ago"); test("2008/01/27 22:23:30", "Yesterday"); test("2008/01/26 22:23:30", "2 days ago"); test("2007/01/26 22:23:30", undefined); console.log("Of " + results.total + " tests, " + results.bad + " failed, " + (results.total - results.bad) + " passed."); /script/headbody/body/html
    • Ejecute este ejemplo. (Asegúrese de habilitar una consola como Firebug o el Inspector web de Chrome).

    Esto creará un marco de prueba ad-hoc, utilizando solo la consola para la salida. No tiene ninguna dependencia del DOM, por lo que también puedes ejecutarlo en un entorno JavaScript sin navegador, como Node.js o Rhino, extrayendo el código de la scriptetiqueta a su propio archivo.

     

    Si una prueba falla, generará el resultado esperado y real para esa prueba. Al final, generará un resumen de la prueba con el número total de pruebas, reprobadas y aprobadas.

    Si todas las pruebas han pasado, como deberían hacerlo aquí, verá lo siguiente en la consola:

    De 6 pruebas, 0 reprobaron y 6 aprobaron.

    Para ver cómo se ve una afirmación fallida, podemos cambiar algo para romperla:

    Se esperaba hace 2 días, pero fue hace 2 días.

    De 6 pruebas, 1 falló y 5 aprobaron.

    Si bien este enfoque ad-hoc es interesante como prueba de concepto (realmente puedes escribir un ejecutor de pruebas en solo unas pocas líneas de código), es mucho más práctico utilizar un marco de prueba unitario existente que proporcione mejores resultados y más infraestructura para escribir. y organización de pruebas.

    El conjunto de pruebas de JavaScript QUnit

    La elección del marco es principalmente una cuestión de gustos. Durante el resto de este artículo, usaremos QUnit (pronunciado “q-unit”), porque su estilo de describir pruebas es similar al de nuestro marco de pruebas ad-hoc.

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleRefactored date examples/title link rel="stylesheet" href="qunit.css" / script src="qunit.js"/script script src="prettydate.js"/script script test("prettydate basics", function() { var now = "2008/01/28 22:25:00"; equal(prettyDate(now, "2008/01/28 22:24:30"), "just now"); equal(prettyDate(now, "2008/01/28 22:23:30"), "1 minute ago"); equal(prettyDate(now, "2008/01/28 21:23:30"), "1 hour ago"); equal(prettyDate(now, "2008/01/27 22:23:30"), "Yesterday"); equal(prettyDate(now, "2008/01/26 22:23:30"), "2 days ago"); equal(prettyDate(now, "2007/01/26 22:23:30"), undefined); }); /script/headbody div/div/body/html
    • Ejecute este ejemplo.

    Aquí vale la pena examinar más de cerca tres secciones. Junto con el texto estándar HTML, tenemos tres archivos incluidos: dos archivos para QUnit ( qunit.cssy qunit.js) y el anterior prettydate.js. Foro ciclismo

    Luego, hay otro bloque de script con las pruebas reales. El testmétodo se llama una vez, pasando una cadena como primer argumento (nombrando la prueba) y pasando una función como segundo argumento (que ejecutará el código real para esta prueba). Luego, este código define la nowvariable, que se reutiliza a continuación, luego llama al equalmétodo varias veces con diferentes argumentos. El equalmétodo es una de varias afirmaciones que proporciona QUnit. El primer argumento es el resultado de una llamada a prettyDate, con la nowvariable como primer argumento y una datecadena como segundo. El segundo argumento equales el resultado esperado. Si los dos argumentos equaltienen el mismo valor, entonces la afirmación será válida; de lo contrario, fallará.

    Finalmente, en el elemento del cuerpo hay algunas marcas específicas de QUnit. Estos elementos son opcionales. Si están presentes, QUnit los utilizará para generar los resultados de la prueba.

     

    El resultado es este:

    Con una prueba fallida, el resultado sería algo como esto:

    Debido a que la prueba contiene una afirmación fallida, QUnit no colapsa los resultados de esa prueba y podemos ver inmediatamente qué salió mal. Junto con la salida de los valores esperados y reales, obtenemos una diferencia diffentre los dos, que puede ser útil para comparar cadenas más grandes. Aquí, es bastante obvio lo que salió mal.

    Refactorización, etapa 1

    Actualmente, las afirmaciones están algo incompletas porque aún no estamos probando la n weeks agovariante. Antes de agregarlo, deberíamos considerar refactorizar el código de prueba. Actualmente, solicitamos prettyDatecada afirmación y pasamos el nowargumento. Podríamos refactorizar esto fácilmente en un método de aserción personalizado:

    test("prettydate basics", function() { function date(then, expected) { equal(prettyDate("2008/01/28 22:25:00", then), expected); } date("2008/01/28 22:24:30", "just now"); date("2008/01/28 22:23:30", "1 minute ago"); date("2008/01/28 21:23:30", "1 hour ago"); date("2008/01/27 22:23:30", "Yesterday"); date("2008/01/26 22:23:30", "2 days ago"); date("2007/01/26 22:23:30", undefined);});
    • Ejecute este ejemplo.

    Aquí hemos extraído la llamada prettyDatea la datefunción, insertando la nowvariable en la función. Terminamos con solo los datos relevantes para cada afirmación, lo que facilita su lectura, mientras que la abstracción subyacente sigue siendo bastante obvia.

    Probando la manipulación DOM

    Ahora que la prettyDatefunción se ha probado suficientemente bien, volvamos a centrarnos en el ejemplo inicial. Junto con la prettyDatefunción, también seleccionó algunos elementos DOM y los actualizó dentro del windowcontrolador de eventos de carga. Aplicando los mismos principios que antes, deberíamos poder refactorizar ese código y probarlo. Además, introduciremos un módulo para estas dos funciones, para evitar saturar el espacio de nombres global y poder dar a estas funciones individuales nombres más significativos.

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleRefactored date examples/title link rel="stylesheet" href="qunit.css" / script src="qunit.js"/script script src="prettydate2.js"/script script test("prettydate.format", function() { function date(then, expected) { equal(prettyDate.format("2008/01/28 22:25:00", then), expected); } date("2008/01/28 22:24:30", "just now"); date("2008/01/28 22:23:30", "1 minute ago"); date("2008/01/28 21:23:30", "1 hour ago"); date("2008/01/27 22:23:30", "Yesterday"); date("2008/01/26 22:23:30", "2 days ago"); date("2007/01/26 22:23:30", undefined); }); test("prettyDate.update", function() { var links = document.getElementById("qunit-fixture").getElementsByTagName("a"); equal(links[0].innerHTML, "January 28th, 2008"); equal(links[2].innerHTML, "January 27th, 2008"); prettyDate.update("2008-01-28T22:25:00Z"); equal(links[0].innerHTML, "2 hours ago"); equal(links[2].innerHTML, "Yesterday"); }); test("prettyDate.update, one day later", function() { var links = document.getElementById("qunit-fixture").getElementsByTagName("a"); equal(links[0].innerHTML, "January 28th, 2008"); equal(links[2].innerHTML, "January 27th, 2008"); prettyDate.update("2008-01-28T22:25:00Z"); equal(links[0].innerHTML, "Yesterday"); equal(links[2].innerHTML, "2 days ago"); }); /script/headbody div/div div ul li pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"January 28th, 2008/a/span by spana href="/john/"John Resig/a/span /small /li li pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"January 27th, 2008/a/span by spana href="/john/"John Resig/a/span /small /li /ul /div/body/html

    Aquí está el contenido de prettydate2.js:

     

    var prettyDate = { format: function(now, time){ var date = new Date(time || ""), diff = (((new Date(now)).getTime() - date.getTime()) / 1000), day_diff = Math.floor(diff / 86400); if (isNaN(day_diff) || day_diff 0 || day_diff = 31) { return; } return day_diff === 0 ( diff 60 "just now" || diff 120 "1 minute ago" || diff 3600 Math.floor( diff / 60 ) + " minutes ago" || diff 7200 "1 hour ago" || diff 86400 Math.floor( diff / 3600 ) + " hours ago") || day_diff === 1 "Yesterday" || day_diff 7 day_diff + " days ago" || day_diff 31 Math.ceil( day_diff / 7 ) + " weeks ago"; }, update: function(now) { var links = document.getElementsByTagName("a"); for ( var i = 0; i links.length; i++ ) { if (links[i].title) { var date = prettyDate.format(now, links[i].title); if (date) { links[i].innerHTML = date; } } } }};
    • Ejecute este ejemplo.

    La nueva prettyDate.updatefunción es un extracto del ejemplo inicial, pero con el nowargumento para pasar a prettyDate.format. La prueba basada en QUnit para esa función comienza seleccionando todos alos elementos dentro del #qunit-fixtureelemento. En el marcado actualizado en el elemento del cuerpo, div…/dives nuevo. Contiene un extracto del marcado de nuestro ejemplo inicial, suficiente para escribir pruebas útiles. Al colocarlo en el #qunit-fixtureelemento, no tenemos que preocuparnos de que los cambios DOM de una prueba afecten a otras pruebas, porque QUnit restablecerá automáticamente el marcado después de cada prueba.

    Veamos la primera prueba para prettyDate.update. Después de seleccionar esos anclajes, dos afirmaciones verifican que estos tengan sus valores de texto iniciales. Posteriormente prettyDate.updatese convoca pasando una fecha fija (la misma que en pruebas anteriores). Luego se ejecutan dos aserciones más, verificando ahora que las innerHTMLpropiedades de estos elementos tengan la fecha formateada correctamente, “Hace 2 horas” y “Ayer”.

     

    Refactorización, etapa 2

    La siguiente prueba, prettyDate.update, one day later, hace casi lo mismo, excepto que pasa en una fecha diferente prettyDate.updatey, por lo tanto, espera resultados diferentes para los dos enlaces. Veamos si podemos refactorizar estas pruebas para eliminar la duplicación.

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleRefactored date examples/title link rel="stylesheet" href="qunit.css" / script src="qunit.js"/script script src="prettydate2.js"/script script test("prettydate.format", function() { function date(then, expected) { equal(prettyDate.format("2008/01/28 22:25:00", then), expected); } date("2008/01/28 22:24:30", "just now"); date("2008/01/28 22:23:30", "1 minute ago"); date("2008/01/28 21:23:30", "1 hour ago"); date("2008/01/27 22:23:30", "Yesterday"); date("2008/01/26 22:23:30", "2 days ago"); date("2007/01/26 22:23:30", undefined); }); function domtest(name, now, first, second) { test(name, function() { var links = document.getElementById("qunit-fixture").getElementsByTagName("a"); equal(links[0].innerHTML, "January 28th, 2008"); equal(links[2].innerHTML, "January 27th, 2008"); prettyDate.update(now); equal(links[0].innerHTML, first); equal(links[2].innerHTML, second); }); } domtest("prettyDate.update", "2008-01-28T22:25:00Z:00", "2 hours ago", "Yesterday"); domtest("prettyDate.update, one day later", "2008-01-29T22:25:00Z:00", "Yesterday", "2 days ago"); /script/headbody div/div div ul li pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"January 28th, 2008/a/span by spana href="/john/"John Resig/a/span /small /li li pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"January 27th, 2008/a/span by spana href="/john/"John Resig/a/span /small /li /ul /div/body/html
    • Ejecute este ejemplo.

    Aquí tenemos una nueva función llamada domtest, que encapsula la lógica de las dos llamadas anteriores a test, introduciendo argumentos para el nombre de la prueba, la cadena de fecha y las dos cadenas esperadas. Luego lo llaman dos veces.

    De vuelta al principio

    Una vez establecido esto, volvamos a nuestro ejemplo inicial y veamos cómo se ve ahora, después de la refactorización.

    !DOCTYPE htmlhtmlhead meta http-equiv="Content-Type" content="text/html; charset=UTF-8" / titleFinal date examples/title script src="prettydate2.js"/script script window.onload = function() { prettyDate.update("2008-01-28T22:25:00Z"); }; /script/headbodyulli pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanJanuary 28th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/lili pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanJanuary 27th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/lili pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanJanuary 26th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/lili pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanJanuary 25th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/lili pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanJanuary 24th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/lili pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanJanuary 14th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/lili pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanJanuary 4th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/lili pblah blah blah…/p small Posted spana href="/2008/01/blah/57/"spanDecember 15th, 2008/span/a/span by spana href="/john/"John Resig/a/span /small/li/ul/body/html
    • Ejecute este ejemplo.

    Para un ejemplo no estático, eliminaríamos el argumento de prettyDate.update. Considerándolo todo, la refactorización es una gran mejora con respecto al primer ejemplo. Y gracias al prettyDatemódulo que presentamos, podemos agregar aún más funciones sin afectar el espacio de nombres global.

    Conclusión

    Probar código JavaScript no es sólo cuestión de utilizar algún ejecutor de pruebas y escribir algunas pruebas; Por lo general, requiere algunos cambios estructurales importantes cuando se aplica a código que antes solo se ha probado manualmente. Hemos analizado un ejemplo de cómo cambiar la estructura del código de un módulo existente para ejecutar algunas pruebas utilizando un marco de pruebas ad-hoc y luego reemplazarlo con un marco con más funciones para obtener resultados visuales útiles.

    QUnit en sí tiene mucho más que ofrecer, con soporte específico para probar código asincrónico como tiempos de espera, AJAX y eventos. Su ejecutor de pruebas visual ayuda a depurar código al facilitar la repetición de pruebas específicas y al proporcionar seguimientos de pila para aserciones fallidas y excepciones detectadas. Para obtener más información, consulte el libro de cocina de QUnit .

    (al) (km)

    Explora más en

    • Codificación
    • javascript
    • Pruebas





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Introducción a las pruebas unitarias de JavaScript

    Introducción a las pruebas unitarias de JavaScript

    SmashingConf UX Design, Antwerp 2024 Design Patterns For AI Interfaces, with Vitaly Friedman Índice Lect

    programar

    es

    https://aprendeprogramando.es/static/images/programar-introduccion-a-las-pruebas-unitarias-de-javascript-800-0.jpg

    2024-05-20

     

    Introducción a las pruebas unitarias de JavaScript
    Introducción a las pruebas unitarias de JavaScript

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20