Postman lleva años siendo la herramienta por defecto a la hora de desarrollar y probar APIs. Sin embargo, salvo que dispongamos de la versión de pago, las funcionalidades que la herramienta ofrece a la comunidad de forma gratuita van reduciéndose poco a poco, y la reciente obligatoriedad de subir nuestras colecciones entornos a su nube ha hecho que mucha gente se plantee otras herramientas alternativas.
Bruno es una de esas alternativas que cumple con muchos de los requisitos que cualquier desarrollador y/o probador de APIs le pide a una herramienta de este tipo:
- Trabaja offline (las colecciones y los entornos se almacenan en el sistema de archivos)
- Su interfaz es muy similar a la de Postman
- Ofrece un CLI similar a Newman
- Adicionalmente, añade una capa de extensibilidad que hará las delicias de cualquier desarrollador.
Instalación
La instalación de Bruno no puede ser más sencilla. Basta con acudir a su repositorio de GitHub y descargarnos la versión deseada. Tenemos clientes para Windows, Linux y Mac, por lo que podremos hacer uso de ella en cualquier plataforma.
Una vez instalado o descomprimido, ejecutamos el binario asociado y nos encontraremos una interfaz que nos resultará bastante familiar, salvo por la presencia de un simpático perrito como mascota de la aplicación:
Colecciones
Crear una colección es tan simple como pulsar en el botón [+ Create Collection] Esto nos mostrará un popup en el que cumplimentaremos la siguiente información:
- Nombre de la colección
- Ruta en la que almacenaremos la colección (todos los datos se almacenan en el sistema de ficheros)
- Nombre de la carpeta en la que almacenaremos la colección
El hecho de que la colección se almacene como un árbol de directorios tiene otras ventajas, como la posibilidad de crear un repositorio compartido con nuestros compañeros en el que almacenar nuestras colecciones.
Dentro de nuestra colección también podemos crear carpetas. En nuestra colección, pulsamos el botón [···] y seleccionamos la opción [New Folder] .
Ahora le asignamos el nombre que queramos
Y con esto, nuestra carpeta estará lista para crear una petición. Para ello, seleccionamos la carpeta o la colección en la que queremos crear nuestra petición y pulsamos [···] y, a continuación, [New Request].
Bruno nos permite realizar dos tipos de peticiones: HTTP o GraphQL. Seleccionamos el tipo que queramos, le asignamos un nombre y rellenamos el tipo de petición y la URL en la que se encuentra el endpoint.
Por supuesto, nuestras peticiones pueden también estar almacenadas en variables, y la sintaxis es similar a la de Postman, encerrando las variables entre llaves dobles ({{variable}}):
Entornos
Al crear la petición, vemos que las variables aparecen resaltadas en color rojo. Esto se debe a que las variables no existen. Para ello, crearemos un entorno en el que las guardaremos, y para ello acudiremos al desplegable que se encuentra en la esquina superior derecha:
Seleccionamos la opción [Configure].
Tenemos la opción de crear un nuevo entorno o de importar un entorno existente. Optaremos por crearlo, seleccionando [Create Environment]:
Le asignamos un nombre a nuestro entorno:
Y finalmente, creamos nuestras variables y les asignamos valor.
Hecho esto, las variables aparecerán en color verde y el entorno seleccionado se mostrará seleccionado en el desplegable de la esquina superior derecha.
Peticiones
El proceso de codificar peticiones es muy similar al que utilizábamos en Postman: dependiendo del tipo de petición podemos configurar los parámetros en la query o en el body. Y pulsando la flecha [->] junto a la URL de la petición, lanzaremos la consulta a nuestro endpoint y obtendremos el resultado en la parte derecha de la pantalla. Como vemos, la interfaz es muy familiar:
Al enviar una petición POST podemos editar el cuerpo de la petición y seleccionar su formato (Multipart, URLEncoded, JSON, text, ...). También podemos editar las cabeceras, al igual que haríamos con Postman.
Variables
Como funcionalidad interesante, Bruno nos permite asignar variables antes o después de la petición sin necesidad de codificarlo explícitamente en un script. Por ejemplo, imaginemos que tenemos un endpoint en el que accedemos a la información de un registro pasándole el id como parte de la ruta, es decir:
Esta variable se muestra en color rojo, ya que no ha sido declarada. Queremos que su valor sea el id devuelto por la operación POST que inserta un registro y devuelve la información almacenada en la base de datos.
¿Cómo podemos hacer esto? A través de la variable global res.
Respuestas
La variable global res nos permite acceder a la respuesta en los scripts post-response, asserts y tests. Para almacenar en una variable un elemento recuperado en una respuesta, seleccionaremos la pestaña [Vars] y en la sección [Post response] , añadiremos en la tabla el nombre de la variable y el valor que debe adquirir. En este caso, queremos que la variable "id" se rellene con el campo "id" obtenido en el cuerpo de la respuesta, por lo que la expresión que asignará valor a la variable será "res.body.id“:
Probemos ahora a ejecutar la petición POST que inserta un registro. Vemos que el id con el que el registro se ha almacenado en base de datos es 796:
Si ahora volvemos a abrir nuestra petición "users", podremos comprobar que la variable {{id}} tiene ahora color verde. Es más, si colocamos el puntero del ratón sobre la variable, Bruno nos mostrará su valor, que coincide con el devuelto en la petición anterior (796):
Autenticación
Otra de las características que ofrece Bruno es la de configurar la autenticación de las peticiones. Al igual que en Postman, es posible utilizar variables para, por ejemplo, almacenar un bearer token y utilizarlo posteriormente en la pestaña [Auth] para autenticar nuestras peticiones.
Asserts
Otra de las características de Bruno es la posibilidad de utilizar aserciones en las peticiones, de modo que no tengamos que codificar pruebas específicas para ello.
Las aserciones son útiles para realizar comprobaciones atómicas, como el estado de una respuesta, la presencia de un campo o cuando esperamos un valor concreto. Los asserts se ejecutan tras obtener la respuesta, y para ello basta con abrir la pestaña [Assert] y completar la tabla.
- Expr: expresión a comprobar
- Operator: operador a aplicar a la expresión
- Value: valor esperado
Las aserciones evalúan la expresión y comprueban que, tras aplicar el operador correspondiente, obtiene el valor esperado.
Tests
Si has manejado Postman con anterioridad, esta pestaña te será familiar. En esta sección podremos codificar pruebas en Javascript, permitiéndonos jugar con los datos tal y como estábamos acostumbrados. No obstante, a diferencia de Postman, los tests están pensados únicamente para codificar pruebas, no para código post-request. Ciertamente, la codificación de esas tareas en esta sección era algo que personalmente no me gustaba demasiado, ya que obligaba al usuario a mezclar dos tareas distintas.
Therefore, if you need to perform tasks that have nothing to do with testing after the execution of a request, it is advisable to do it in its corresponding section ([Script] > [Post Response]).
Bruno también ofrece la variable global "bru", que actúa de forma similar a como "pm" funciona en Postman ofreciendo una interfaz para interactuar con el entorno. La documentación de la herramienta ofrece un listado de métodos y funciones disponibles, como leer y guardar variables y otras tareas similares.
Collection Runner
Una de las funcionalidades que Postman limitó hace tiempo fue la posiblidad de ejecutar colecciones o carpetas completas. Bruno permite realizarlo sin restricción alguna, y en dos sabores diferentes:
- Ejecutar una colección: ejecuta las peticiones de la carpeta actual, pero no las de las subcarpetas
- Ejecutar una colección de forma recursiva: ejecuta todas las peticiones de la carpeta actual y las de sus subcarpetas
Hacer uso de esta funcionalidad es sencillo: basta pulsar el botón [···] de una carpeta y seleccionar la opción [Run] . Esto abrirá un popup que nos permitirá realizar una de estas dos operaciones:
El resultado de la ejecución se mostrará en la pestaña "Runner":
Bola extra: extensibilidad
Dejo para el final una de las funcionalidades de Bruno que más me han encantado: su extensibilidad.
Bruno nos permite utilizar cualquier paquete npm dentro del entorno. Sí, CUALQUIER paquete npm. Para ello, es tan sencillo como acceder a la carpeta en la que se encuentra nuestra colección e inicializar un proyecto npm o crear un fichero package.json :
Una vez tenemos nuestro proyecto inicializado, instalaremos paquetes como si de un proyecto node se tratase. Por ejemplo, instalaremos el paquete @faker-js/faker para mockear datos en nuestras peticiones:
Finalmente, dentro de la pestaña [Script] importaremos y utilizaremos los paquetes que hemos importado de manera normal. En este caso, la variable global "req" nos permite interactuar con la petición antes de su envío.
Además de todo esto, es posible editar el fichero con la configuración de la colección, bruno.json
y añadir soporte para funcionalidades como acceso al sistema de ficheros o añadir a la lista blanca paquetes como form-data
:
{
"version": "1",
"name": "MyCollection",
"type": "collection",
"scripts": {
"moduleWhitelist": ["form-data"],
"filesystemAccess": {
"allow": true
}
}
}
En esta discusión de GitHub puedes encontrar algunos trucos y snippets sobre cómo realizar magia con esta maravillosa herramienta, como subir archivos o implementar un autenticador OAuth2 automático antes de ejecutar una petición. ¡Merece la pena probarlo!
Más información:
- Bruno homepage
- Bruno git repository
- Bruno documentation
- Bruno Scriptmania (recetas y snippets para Bruno)