unitarios unitarias unit tutorial test pruebas espaƱol javascript testing tdd

unitarias - test unitarios javascript



Desarrollo basado en pruebas de interfaces web de JavaScript (6)

Esto puede sonar un poco tonto, pero en realidad estoy un poco confundido sobre cómo abordar las pruebas de JavaScript para interfaces web. En lo que a mí respecta, la típica arquitectura de 3 niveles se ve así:

  1. Nivel de base
  2. Nivel de aplicación
  3. Nivel del cliente

1 no tiene importancia en esta pregunta. 2 contiene toda la lógica del programa ("lógica de negocios") 3 la interfaz.

Hago un desarrollo basado en pruebas para la mayoría de los proyectos, pero solo para la lógica de la aplicación, no para la interfaz. Eso es porque probar la IU es difícil e inusual en TDD, y normalmente no se hace. En cambio, toda la lógica de la aplicación está separada de la interfaz de usuario, por lo que es simple probar esa lógica.

La arquitectura de tres niveles es compatible con esto: puedo diseñar mi backend como una API REST a la que llama mi frontend. ¿Cómo encajan las pruebas JS? Para la típica arquitectura de tres niveles, las pruebas de JS (es decir, JS en el cliente) no tienen mucho sentido, ¿o sí?

Actualización: Cambié la redacción de la pregunta de "Prueba de JavaScript en interfaces web" a "Desarrollo basado en pruebas de interfaces web de JavaScript" para aclarar mi pregunta.


Eche un vistazo a QUnit , también, para pruebas unitarias de métodos y funciones de JavaScript.



Hay un libro titulado Test-Driven JavaScript Development de Christian Johansen que podría ayudarte. Solo he visto algunas de las muestras en el libro (simplemente descargué una muestra a Kindle el otro día) pero parece un gran libro que aborda este mismo tema. Deberías revisarlo.

(Nota: no tengo ninguna conexión con Christian Johansen ni ninguna inversión en la venta del libro. Simplemente parece una buena cosa que aborda este problema).


Puede probar su aplicación desde la perspectiva del usuario con herramientas como Rational Functional Tester , las herramientas de HP u otro software equivalente.

Estas herramientas prueban la aplicación como si un usuario estuviera sentado frente a ella, pero de forma automatizada. Esto significa que puede probar los tres niveles al mismo tiempo, y especialmente el Javascript que puede ser difícil de probar de lo contrario. Las pruebas funcionales de este tipo pueden ayudar a encontrar errores de IU y peculiaridades con la forma en que la IU está utilizando los datos extraídos de su nivel medio.

Lamentablemente, estas herramientas son muy costosas, por lo que puede haber otros equivalentes (y me gustaría saber de tales herramientas).


Recuerde cuál es el punto de las pruebas unitarias: para garantizar que un módulo particular de código reaccione a algunos estímulos de la manera esperada. En JS, una parte importante de su código (a menos que tenga algún marco de ciclo de vida como Sencha o YUI) manipulará directamente el DOM o realizará llamadas remotas. Para probar estas cosas, simplemente aplica las técnicas tradicionales de pruebas unitarias de inyección de dependencia y burla / stubbing. Eso significa que debe escribir cada función, o clase, que desea que la prueba unitaria acepte simulacros de las estructuras dependientes.

jQuery lo admite al permitirle pasar un documento XML a todas las funciones transversales. Mientras que normalmente podrías escribir

$(function() { $(''.bright'').css(''color'',''yellow''); }

en su lugar querrás escribir

function processBright(scope) { // jQuery will do the following line automatically, but for sake of clarity: scope = scope || window.document; $(''.bright'',scope).css(''color'',''yellow''); } $(processBright);

Tenga en cuenta que no solo sacamos la lógica de la función anónima y le damos un nombre, también hacemos que esa función acepte un parámetro de alcance. Cuando ese valor es nulo, las llamadas jQuery seguirán funcionando normalmente. Sin embargo, ahora tenemos un vector para inyectar un documento simulado que podemos inspeccionar después de invocar la función. La prueba de unidad podría verse como

function shouldSetColorYellowIfClassBright() { // arrange var testDoc = $(''<html><body><span id="a" class="bright">test</span></body></html>''); // act processBright(testDoc); // assert if (testDoc.find(''#a'').css(''color'') != ''bright'') throw TestFailed("Color property was not changed correctly."); }

TestFailed podría verse así:

function TestFailed(message) { this.message = message; this.name = "TestFailed"; }

La situación es similar con las llamadas remotas, aunque en lugar de inyectar realmente alguna instalación, se puede salir con un trozo de máscara. Digamos que tienes esta función:

function makeRemoteCall(data, callback) { if (data.property == ''ok'') $.getJSON({url:''/someResource.json'',callback:callback}); }

Lo probarías como tal:

// test suite setup var getJSON = $.getJSON; var stubCalls = []; $.getJSON = function(args) { stubCalls[stubCalls.length] = args.url; } // unit test 1 function shouldMakeRemoteCallWithOkProperty() { // arrange var arg = { property: ''ok'' }; // act makeRemoteCall(arg); // assert if (stubCalls.length != 1 || stubCalls[0] != ''/someResource.json'') throw TestFailed("someResource.json was not requested once and only once."); } // unit test 2 function shouldNotMakeRemoteCallWithoutOkProperty() { // arrange var arg = { property: ''foobar'' }; // act makeRemoteCall(arg); // assert if (stubCalls.length != 0) throw TestFailed(stubCalls[0] + " was called unexpectedly."); } // test suite teardown $.getJSON = getJSON;

(Puede envolver todo eso en el patrón del módulo para no ensuciar el espacio de nombres global).

Para aplicar todo esto de forma guiada por pruebas, simplemente debe escribir estas pruebas primero. Esta es una forma sencilla, sin complicaciones, y lo más importante, efectiva de probar unidades JS.

Los marcos como qUnit pueden usarse para conducir sus pruebas unitarias, pero eso es solo una pequeña parte del problema. Su código debe escribirse de manera amigable para las pruebas. Además, los frameworks como Selenium, HtmlUnit, jsTestDriver o Watir / N son para pruebas de integración, no para pruebas unitarias per se. Por último, de ninguna manera debe su código estar orientado a objetos. Los principios de pruebas unitarias se confunden fácilmente con la aplicación práctica de pruebas unitarias en sistemas orientados a objetos. Son ideas separadas pero compatibles.

Estilos de prueba

Debo señalar que aquí se muestran dos estilos de prueba diferentes. El primero asume ignorancia completa de la implementación de processBright. Podría estar usando jQuery para agregar el estilo de color, o podría estar haciendo la manipulación DOM nativa. Estoy simplemente probando que el comportamiento externo de la función es el esperado . En el segundo, asumo el conocimiento de una dependencia interna de la función (es decir, $ .getJSON), y esas pruebas cubren la interacción correcta con esa dependencia .

El enfoque que toma depende de su filosofía de evaluación y las prioridades generales y el perfil de costo-beneficio de su situación. La primera prueba es relativamente pura. La segunda prueba es simple pero relativamente frágil; si cambio la implementación de makeRemoteCall, la prueba se romperá. Preferiblemente, la suposición de que makeRemoteCall usa $ .getJSON está al menos justificada por la documentación de makeRemoteCall. Hay un par de enfoques más disciplinados, pero un enfoque rentable es ajustar las dependencias en las funciones de contenedor. La base de código dependería únicamente de estos envoltorios, cuyas implementaciones pueden reemplazarse fácilmente con comprobantes de prueba en el momento de la prueba.


Tengo una aplicación de arquitectura similar con nivel de cliente JS. En mi caso, utilizo el propio marco JS de nuestra empresa para implementar el nivel del cliente.

Este marco JS se crea en estilo OOP, por lo que puedo implementar pruebas unitarias para las clases y componentes principales. Además, para cubrir todas las interacciones del usuario (que no se pueden cubrir mediante pruebas unitarias), estoy usando Selenium WebDriver para realizar una prueba de integración de componentes visuales marco y probarlos en diferentes navegadores.

Entonces, TDD se puede aplicar al desarrollo de JavaScript si el código bajo prueba está escrito en modo OOP. También es posible la prueba de integración (y se puede usar para hacer algún tipo de TDD).