Conoce a JSCheck de Crockford

Hay docenas de marcos de prueba de JavaScript, pero la mayoría de ellos funcionan, más o menos, de la misma manera. Sin embargo, JSCheck de Douglas Crockford es considerablemente diferente de la mayoría. En este tutorial, te mostraré cómo es diferente y por qué deberías considerar usarlo!


Crockford describe JSCheck como una "herramienta de prueba basada en especificaciones.

Crockford describe JSCheck como una "herramienta de prueba basada en especificaciones". Cuando usa los marcos a los que está acostumbrado, escribiría una prueba para una determinada funcionalidad y, si esa prueba pasa, declare que la funcionalidad dada funciona correctamente. . Sin embargo, es posible que se pierda algunos de los casos extremos o excepciones que sus exámenes no cubren..

Aunque descubrir casos extremos no es el propósito expreso de JSCheck, es un beneficio secundario agradable. La idea principal detrás de JSCheck es esta: la especificación que escriba describirá realmente cómo debería funcionar el código que está probando. Entonces, JSCheck tomará esa especificación (llamada Reclamación en JSCheck-lingo), y generar pruebas aleatorias para probar el reclamo. Finalmente, te reportará los resultados..

¿Suena interesante? Sigue leyendo ¿Suena familiar? Es posible que haya utilizado la herramienta de prueba de Haskell, QuickCheck, en la que se basó JSCheck.


Algún código para probar

Por supuesto, antes de escribir nuestro reclamo, querremos tener un código para probar. Recientemente, escribí un marcador de mini-contraseña, similar a la funcionalidad de HowSecureIsMyPassword.net. Realmente no es lujoso: solo le pasas una contraseña a la función y obtienes una puntuación. Aquí está el código:

passwordScorer.js

(function () var PasswordScorer = ; PasswordScorer.score = function (password) var len = password.length, lengthScore = 0, letterScore = 0, chars =  if (len> = 21) lengthScore = 7 ; else if (len> = 16) lengthScore = 6; else if (len> = 13) lengthScore = 5; else if (len> = 10) lengthScore = 4; else if (len> = 8) lengthScore = 3; else if (len> = 5) lengthScore = 2; var re = [null, / [az] / g, / [AZ] / g, / \ d / g, / [ ! @ # $% \ ^ & \ * \ (\) = _ + -] / g]; para (var i = 1; i < re.length; i++)  letterScore += (password.match(re[i]) || []).length * i;  return letterScore + lengthScore; ; (typeof window !== 'undefined' ? window : exports).PasswordScorer = PasswordScorer; ());

Es un código bastante simple, pero esto es lo que está pasando: el puntaje se compone de dos sub-puntajes. Hay un puntaje inicial, que se basa en la longitud de la contraseña, y luego un puntaje adicional para cada personaje, 1 punto por cada letra minúscula, 2 puntos por cada letra mayúscula, 3 puntos por cada número y 4 puntos por cada símbolo ( de un conjunto limitado).

Entonces, este es el código que vamos a probar: generaremos algunas contraseñas al azar con JSCheck y nos aseguraremos de que obtengan una puntuación adecuada.


Escribiendo nuestro reclamo

Ahora estamos listos para escribir nuestros reclamos. Primero, dirígete a la página JSCheck Github y descarga el jscheck.js expediente. Me gusta ejecutar mis pruebas en el terminal, a través de NodeJS, así que agregue esta línea única al final del archivo:

(typeof window! == 'undefined'? window: exports) .JSC = JSC;

Esto no afectará en absoluto al comportamiento del archivo en el navegador, pero lo hará funcionar como un módulo dentro del Nodo. Tenga en cuenta que el jscheck.js archivo expone JSC como la única variable global para toda la biblioteca. Si no estuviéramos haciendo este ajuste, así es como lo haríamos.

Vamos a abrir passwordScorerSpec.js y empezar cosas:

JSC = require ("./ ... /vendor/jschec";).JSC; PasswordScorer = require ("./ ... /lib/passwordScore";).PasswordScorer;

Ya que estoy ejecutando estas pruebas en NodeJS, tendremos que requerir los módulos que queremos. Por supuesto, querrá asegurarse de que las rutas coincidan con las ubicaciones de sus archivos..

Ahora, estamos listos para escribir nuestro primer reclamo. Por supuesto, usamos el JSC.claim método. Este método acepta tres parámetros, con un cuarto opcional. El primer parámetro es solo una cadena, una nombre para la reclamación. El segundo parámetro se llama predicado: es la función de prueba real. Muy simple, esta función debería volver. cierto si la afirmación es cierta, y falso si el reclamo es falso Los valores aleatorios que JSCheck generará para la prueba se pasarán como parámetros al predicado.

Pero, ¿cómo sabe JSCheck qué tipo de valores aleatorios debe entregar el predicado? Ahí es donde el tercer parámetro, el especificador entra en juego. Esta es una matriz, con un elemento para cada parámetro para predicado. Los elementos en la matriz especifican qué tipos dar el predicado, utilizando las funciones del especificador de JSCheck. Éstos son algunos de ellos:

  • JSC.boolean () devuelve verdadero o falso.
  • JSC.caracter () toma un carácter mínimo y máximo y devuelve un solo carácter de ese rango. También puede tomar un solo código de carácter y devolver ese carácter..
  • JSC.integer () devolverá un número primo. O, pásale un solo parámetro para obtener un entero (número entero) entre 1 y el parámetro, o dos parámetros para un entero en ese rango.

Tienes la idea Hay otros especificadores, y usaremos algunos ahora mientras escribimos nuestro primer reclamo.

JSC.claim ("Toda la contraseña en minúscula" ;, función (password, maxScore) return PasswordScorer.score (password) <= maxScore; , [ JSC.string(JSC.integer(10, 20), JSC.character('a', 'z')), JSC.literal(26) ]);

Nuestro primer parámetro es un nombre. La segunda es la función de prueba: recibe una contraseña y una puntuación máxima, y ​​devuelve verdadero si la puntuación de esa contraseña es menor o igual que la puntuación máxima. Entonces, tenemos nuestro array especificador. Nuestro primer parámetro (la contraseña) debe ser una cadena, por lo que usamos el JSC.string () Método: puede tomar dos parámetros, el número de caracteres en la cadena y el valor de esos caracteres. Como puede ver, pedimos una contraseña de entre 10 y 20 caracteres. Para el valor, estamos usando el Caracteres JSC () Método para obtener caracteres aleatorios entre 'a' y 'z'.

El siguiente valor es nuestro maximo puntaje parámetro. A veces, no queremos la aleatoriedad que ofrece JSCheck, y este es uno de esos momentos. Por eso hay JSC.literal: para pasar un valor literal el predicado. En este caso, estamos usando 26, que debería ser el puntaje máximo para cualquier contraseña en minúscula entre 10 y 20 caracteres.

Ahora estamos listos para ejecutar la prueba.


Ejecutando nuestro reclamo

Antes de que realicemos la reclamación y obtengamos el informe, debemos configurar la función que recibirá el informe. JSCheck pasa el informe a una función de devolución de llamada de JSC.on_report. Por lo tanto:

JSC.on_report (function (str) console.log (str););

Nada sofisticado. Ahora, todo lo que queda es llamar JSC.check (). Ahora, podemos dirigirnos a nuestra terminal y ejecutar esto:

ruta del nodo / a / passwordScorerSpec.js

Detrás de escena, JSCheck ejecuta el predicado 100 veces, generando diferentes valores aleatorios cada vez. Debería ver su informe impreso.

Todas las contraseñas en minúscula 100 de 100 pasan 100

Todos pasaron, pero eso no es un gran informe, ¿eh? Bueno, si alguna de nuestras pruebas hubiera fallado, se habrían incluido en el informe. Sin embargo, puede ajustar el nivel de salida con el JSC.detail Función: pásele un número entre 0 y 4 (inclusive) para obtener cualquier cosa sin salida en todos los casos de prueba. El valor predeterminado es 3..


Añadiendo un clasificador

Recuerda como dije eso JSC.claim ¿Podría tomar un cuarto parámetro? Se llama un clasificador, y recibe los mismos parámetros que recibe el predicado. Luego, puede devolver una cadena para clasificar, o agrupar, nuestros casos de prueba. Admito que no estaba realmente seguro de dónde sería útil hasta que estaba creando la reclamación del ejemplo anterior. Mira, cometí un error en el predicado y comparé la puntuación con la maximo puntaje con el operador en lugar de la operador, por lo que las contraseñas que obtuvieron 26 puntos fallaron. Estaba viendo informes que se parecían a esto:

Todas las contraseñas en minúsculas 96 de 100 FALLA [12] ("vqfqkqqbbkkjjrvplkrx";, 26) FALLA [21] ("nhgkznldvoenhqqlfza";, 26) Perros de los tipos de recreo de las partes de las partes de los animales y animales de los que se trata, por ejemplo: ;, 26) pasar 96 fallar 4

Todavía no es del todo obvio por qué algunas pruebas están fallando. Así que agregué una función clasificadora que agrupaba los casos de prueba por puntuación: como dije, la función toma los mismos parámetros que el predicado y devuelve una cadena. Cada caso de prueba que recupera la misma cadena del clasificador se agrupará en el informe.

función (contraseña, maxScore) return PasswordScorer.score (contraseña) + "puntos" ;; 

Esta función debe ser el último parámetro de nuestra reclamación. Ahora, obtendrá un informe que es algo como esto:

Todas las contraseñas en minúscula 96 de 100 FALLA [4] 26 puntos :( "illqbtiubsmrhxdwjfo";, 26) FALLA [22] 26 puntos :( "gruvmmqjzqlcyaozgfh";, 26) FALLA [34] 26 puntos :( "chuviqvlhqslprqcc"; ) FALLO [65] 26 puntos :( "kskqdjhtonybvfewdjm";, 26) 14 puntos: pase 8 15 puntos: pasa 5 16 puntos: pasa 12 18 puntos: pasa 10 19 puntos: pasa 12 20 puntos: pasa 11 22 puntos: pasa 12 23 puntos: pase 8 24 puntos: pasa 10 25 puntos: pasa 8 26 puntos: pasa 0 falla 4

Puede ver cómo se agrupan las pruebas según la cantidad de puntos que valen las contraseñas. Ahora, es fácil ver que las únicas contraseñas que no pasan las pruebas son las que obtienen 26 puntos. Y aunque el problema aquí fue con la prueba, y no con el código, todavía muestra cómo puede ser útil agregar una función clasificadora a sus reclamos.


Pensamientos finales

Entonces, al final del día, ¿vale la pena usar JSCheck? Esto es lo que pienso: no es algo que necesariamente vayas a usar con cada base de código, pero a veces te resultará útil poder crear casos de prueba aleatorios que probarán rigurosamente una determinada pieza de código. Cuando eso es lo que quieres hacer, no he visto una herramienta mejor para eso que JSCheck.

JSCheck tiene algunas otras opciones y un montón de especificadores que no hemos revisado en este tutorial; Dirígete a JSCheck.og para leer sobre esos. De lo contrario, me encantaría escuchar sus pensamientos acerca de JSCheck en los comentarios.!