Usar AVA para tests en una API hecha en Node.js y Express

Testear nuestras aplicaciones es algo fundamental si queremos garantizar un mínimo de calidad. En este breve post, explicaré como he usado AVA para crear tests para mis APIs: tanto unitarios como de integración con AVA.

AVA es una herramienta de testing, que nos permite describir los tests de forma muy sencilla. De todas las herramientas que he probado, AVA es muy preferida. Es muy sencilla, ejecuta los tests en paralelo y permite escribir código en ES6 (usa Babel por debajo). Además tiene bastante soporte siendo el framework de testing usando por muchos proyectos ya.

Instalamos AVA de la forma típica:

A continuación creamos un fichero cuya terminación sea .test.js, por ejemplo, suma.test.js. El lugar da igual.

Una opción de diseño es poner los test unitarios al lado de las funciones en sí, otra opción es crear una carpeta para todos los tests, ya que los de integración van a ir casi siempre ahí. Para ejecutar los tests, simplemente:

El interior de suma.test.js debe importar la función test de AVA y las funciones que quiera probar.

Los tests se definen como una llamada a la función test con la descripción del test y a continuación un callback (asíncrono si queremos) con el objeto que controla los tests (llamado t normalmente). Veamos un ejemplo simple:

El objeto t soporta múltiples operaciones, siendo is la más básica. Is pide que sus dos argumentos sean iguales entre sí, como Assert.Equal de xUnit.

Veamos que más soporta Ava.

  • t.pass(): Continúa el test (sigue)
  • t.fail(): Falla el test (no sigue)
  • t.truthy(val): Continúa el test si val es verdaderoso (usando la lógica de JavaScript) o falla el test
  • t.true(val): Continúa el test si val es verdadero (más estricto que el anterior) o falla.
  • t.is(val1,val2): Continúa el test si val1 y val2 son iguales (superficialmente) o falla.
  • t.deepEqual(val1,val2): Continúa el test si val1 y val2 son iguales (profundamente) o falla.
  • t.throws(funcion): Ejecuta la función especificada esperando que lance una excepción. Si no lo hace, falla el test. Se puede especificar el tipo de excepción que esperamos en el segundo argumento.
  • t.notThrows(funcion): Exactamente lo contrario que la anterior.

Y algunas más, pero estas son las esenciales.

También podemos definir funciones que se ejecuten antes y después de nuestros tests, y una sola vez o con cada test. Podemos usar test.before, test.beforeEach, test.after y test.afterEach en vez de test. Por ejemplo, si tienes una base de datos que necesita inicialización, puedes definir ese código en test.before y la limpieza en test.after.

 

Con esto ya podemos hacer tests unitarios, pero no podemos probar la aplicación web al 100%. Entra en acción supertest que nos permitirá tener un servidor Express simulado para que los tests puedan probar la aplicación al completo.

Supertest

Instalamos supertest


En el fichero de test necesitamos crear un objeto de tipo aplicación de Express. Este objeto puede ser el mismo que usas en tu aplicación real o ser una versión simplificada con lo que quieras probar.

Aquí la función de test es asíncrona, AVA es compatible con ambos tipos. Supertest es muy completo y permite probar APIs enteras con su sencilla interfaz que junto con AVA, se convierte en algo casi obligatorio para una aplicación que vaya a producción.

Programando para Haiku – Barras de menús – Parte III

Seguimos con los tutoriales de Haiku, hoy veremos como crear barras de menú. Partimos del código de la ventana vacía, lo tienes en la foto junto con el comando de compilación.

MiAplicacionHaikuCodigo
Haz click en la imagen para verlo en grande

Debemos saber que en la API de BeOS hay tres clases que nos van a servir.

  • BMenuBar, se trata de la barra en sí, que esta pegada a la ventana. Un BMenuBar contiene BMenus.
  • BMenu, son los menús en sí. Un menú es un elemento que contiene acciones, organizadas como si fuera una lista. Los menús no definen acciones, pero sí su organización. Así, a un BMenu le tendremos que añadir BMenuItems u otro BMenus (menús anidados).
  • BMenuItem, son las acciones de los menús. Cada BMenuItem tiene la capacidad de generar un BMessage nuevo, listo para ser procesado por nuestra aplicación.

En la imagen se puede ver perfectamente

BMenu

Vamos a crear una barra de menú con dos menús, uno de ellos simple y otro con un menú anidado y un separador.

Y el resultado es el siguiente:

BMenuBar

Como vemos, SetShortcut hace que los menús sean seleccionables con combinaciones de teclado. Hay que tener en cuenta que en BeOS, la tecla que en Windows normalmente Ctrl, es Alt. Así operaciones como copiar y pegar con Alt+C y Alt+V. Para responder al evento solo hace falta escuchar en la función MessageReceived. En el caso de B_QUIT_REQUESTED, el mensaje ya está implementado en la función QuitRequested.

ShortKin.gq, un acortador de enlaces anónimo

ShortKin.gq es un proyecto en el que he trabajado solamente dos días, sin embargo, creo que ya puede ser de utilidad. Se trata de un acortador de enlaces, gratuito y anónimo. Los enlaces durán para siempre pero nadie sabe quien los creó. El servicio no dispone de anuncios, por lo que puedes estar tranquilo y usarlo donde te apetezca, no será baneado de foros y redes sociales. Actualmente usa Heroku

ShortKing

Bonus: API pública

Puedes usar ShortKin.gq en tu propio proyecto a través de una API muy sencilla. Simplemente has de llamar a:

Y se te devolverá el enlace acortado. Muy fácil de usar en tus aplicaciones. Si tus aplicaciones usan Node.js recuerda que puedes usar unos paquetes de acortadores que programé para que todo fuese más sencillo.

Crear credenciales OAuth2 para Google

Google dispone de muchas APIs a nuestra disposición de forma gratuita. Para poder usarla es necesario que hayamos iniciado sesión. Desde un navegador como Firefox o Chrome es muy sencillo, introducimos nuestro usuario y contraseña y ya podemos acceder a Gmail, YouTube, etc. Si queremos hacerlo desde nuestro propio programa también es posible, pero el procedimiento es distinto. Una vez hagamos esto podremos hacer lo mismo que haría un usuario, lo único que programándolo (leer los contactos, leer el correo, modificar suscripciones de YouTube, publicar en Blogger, etc).

Crea un proyecto de API

Crea un proyecto de Google y crea unos credenciales nuevos en la consola de APIs de Google.

screenshot-console developers google com 2016-07-26 14-52-43

Los credenciales pueden ser de varios tipos: clave de API, ID de OAuth y cuenta de servicio. La clave de API solo funciona en algunas API, el ID de OAuth es el sistema universal y la cuenta de servicio es para APIs de desarrollo. Creamos un ID de OAuth, pues es el método más universal.

screenshot-console developers google com 2016-07-26 16-29-16

Dependiendo de dónde opere nuestra aplicación tendremos un método u otro. El método Web requiere disponer de un servidor web y es el sistema óptimo si tenemos una aplicación Web (por ejemplo, tenemos una red social y queremos una opción de leer contactos de Gmail, usaríamos Web, pues es el procedimiento más cómodo). Si tu programa no tiene un servidor web detrás (es un programa normal de Windows, una herramienta de línea de comandos, un plugin de Firefox,…) usa Otro. Voy a explicar como funciona Otro.

screenshot-console developers google com 2016-07-26 16-30-31

Obtendremos un ID de cliente y un secreto de cliente. Guardamos esas dos claves, son muy importantes. Ahora vamos a activar las APIs. A la izquierda accedemos a Biblioteca. Buscamos la APIs que queramos usar y las activamos.

screenshot-console developers google com 2016-07-26 16-36-27

Obteniendo un access_token y un refresh_token

Para poder llamar a la API de Google es necesario tener un access_token. Los access_token caducan a las pocas horas. Para poder seguir realizando operaciones en la API pasado ese tiempo necesitamos un refresh_token. El refresh_token sirve exclusivamente para pedir un access_token nuevo. Este no caduca, pero no garantiza que siempre nos devuelva un access_token pues puede que el usuario haya decidido eliminar el permiso a nuestro programa.

El procedimiento de OAuth2 es el siguiente:

  1. Nuestra aplicación quiere autenticar al usuario en Google
  2. Nuestra aplicación genera una URL especial que debe abrir el usuario en el navegador
  3. En esa URL inicia sesión en Google el usuario, igual que si fuera a iniciar sesión en Gmail
  4. Se le informa al usuario de los permisos/APIs que nuestro programa quiere usar
  5. El usuario acepta o rechaza
  6. Si acepta ocurren varias cosas dependiendo del método. Si elegiste Otro se mostrará un código que deberás copiar en la aplicación.
  7. Ese código la aplicación lo envía a Google junto a nuestros datos de client ID y client secret.
  8. Google nos envía el access_token y el refresh_token.

Elaborar la URL de inicio de sesión

En la URL de inicio de sesión figuran varios datos.

  • El tipo de petición
  • Los permisos o APIs a las que queremos acceder (scopes)
  • Nuestro ID de cliente
  • Y la URL de redirección, que en nuestro caso, es especial.

En este ejemplo vemos una petición, con dos APIs o permisos, Chrome WebStore y Google Play.

Validar el código

El usuario nos dará el código que le haya dado Google. Nosotros ahora para obtener el access_token y el refresh_token tenemos que enviarlo de vuelta. En Curl el comando sería el siguiente:

La respuesta, en un fichero JSON, contendrá el access_token y el refresh_token. En las librerías de APIs de Google muchas veces basta con especificar el client ID, el client secret y el refresh_token, pues se encargan de pedir automáticamente el access_token.