Bruno es un cliente de API de código abierto que, desde hace algún tiempo, se está difundiendo rápidamente, ganando terreno frente al popularísimo Postman.
Se trata de un proyecto que quiere crecer con el apoyo de su propia comunidad, sin la participación de empresas externas (excepto como patrocinadores) y, sobre todo, con la firme voluntad de no dejarse adquirir. En resumen, quieren caminar por sus propios medios, manteniendo su propia identidad, aceptando ayudas externas, pero sin permitir ninguna interferencia en la gestión del proyecto.
En estos tiempos, es sin duda una noble intención, esperemos que dure.
¿Por qué Bruno?
Para mí, Postman siempre ha sido sinónimo de «fiabilidad» y «costumbre». A pesar de algunos pequeños detalles (como no poder modificar las solicitudes si no es a través de su interfaz), siempre ha cumplido con mis necesidades. Mi característica pereza ha hecho el resto: todas mis colecciones han estado allí desde tiempos inmemoriales, y la idea de reorganizarlas en otro lugar siempre me ha puesto la piel de gallina.
Todo era perfecto hasta que me encontré en la necesidad de compartir «seriamente» mis solicitudes con el equipo para una colaboración efectiva. Entre los costos de la suscripción y la gestión compartida de las llamadas, que requiere frecuentes variaciones al inicio, mi perplejidad crecía diariamente.
Entonces llega Bruno (que me recuerda mucho al título de una película…), que con su simplicidad arquitectónica captura inmediatamente mi atención, llevándome incluso a importar algunas colecciones de Postman.
En este post, intento resumir los puntos de «contacto» (o, si se prefiere, de «fricción») entre los dos competidores, analizándolos desde ambos puntos de vista para llegar a decretar – aunque sea posible – el ganador de esta contienda. ¡Empecemos!
Guardado de Configuraciones
Mientras que Postman guarda las configuraciones de colecciones y solicitudes en su nube, Bruno las almacena en el sistema de archivos de la máquina local, en sus archivos “bru”. Aunque esto pueda parecer un detalle menor, en realidad es una diferencia enorme que repercute significativamente en la colaboración (de la cual hablaremos más adelante), la usabilidad y la privacidad.
En términos de usabilidad, para modificar colecciones y solicitudes, además de la interfaz de Bruno, podemos modificar directamente los archivos de configuración (los “.bru” precisamente) que, en su versión más simple, son similares a lo siguiente:
Un excelente editor que recomiendo para la edición de los archivos Bru es Visual Studio Code, para el cual existe una extensión llamada «Bruno» que implementa el resaltado de sintaxis para facilitar su gestión.
Además, es importante señalar que Bruno no tiene su propia nube (y, según su Manifiesto, es muy probable que nunca la tenga), por lo que la persistencia de las configuraciones es totalmente responsabilidad del usuario. Así, considerando que los archivos de configuración de las colecciones y las solicitudes residen únicamente en el sistema de archivos de nuestras máquinas, la privacidad está garantizada al 100%. La eventual compartición de estos archivos está exclusivamente en nuestras manos.
Bruno vs Postman: el aspecto de la colaboración
A diferencia de la filosofía de Postman, que almacena nuestras configuraciones en algún rincón indefinido de su nube, Bruno guarda las definiciones de las solicitudes y colecciones en nuestro sistema de archivos local, representadas por archivos de texto en formato Bru.
Por lo tanto, aunque en Postman puedo hacer una copia de seguridad exportando mi colección, en Bruno puedo transformar fácilmente mi estructura en el sistema de archivos en un repositorio Git (o SVN, o Mercurial…) para subirlo a BitBucket, GitHub o GitLab, entre otros.
¡Así, hemos implementado la colaboración a nivel de equipo!
Mientras que Postman nos obliga a comprar licencias para equipos de más de 3 usuarios (con precios no precisamente «populares»), Bruno nos ofrece esta posibilidad de forma gratuita y sin ningún límite desde el principio: depende de nosotros decidir qué solicitudes compartir y con quién. ¿No es maravilloso?
¿Online? ¡Desconectado!
Debo admitir que nunca me había percatado de este detalle, ya que en mi rutina diaria siempre estoy conectado. Sin embargo, parece que Postman solo funciona en modo «en línea». Es decir, no se inicia si no puede contactar con sus servidores (¡¿pero por qué?!).
En contraste, Bruno no requiere ninguna conexión, ya que todo lo que necesita está en el sistema de archivos local. Esto significa que es posible, durante el desarrollo de un servicio, realizar llamadas al entorno local incluso si estás desconectado del resto del mundo.
Este es otro «detalle» que refuerza aún más el respeto que Bruno tiene por nuestra privacidad.
Uso de Librerías Externas
Para un desarrollador, utilizar librerías externas es algo habitual (la rueda y el fuego ya fueron inventados hace tiempo, no es necesario reinventarlos) y esto también se aplica en este contexto.
Tanto Postman como Bruno ofrecen librerías preinstaladas, listas para usar, que pueden cubrir la mayoría de nuestras necesidades, por ejemplo:
Postman | Libreria | Bruno |
X | ajv | X |
axios | X | |
node-fetch | X | |
X | atob | X |
X | btoa | X |
X | chai | X |
X | lodash | X |
X | moment | X |
X | uuid | X |
nanoid | X | |
X | crypto-js | X |
X | cheerio | |
X | csv-parse | |
X | tv4 | |
X | xml2js | |
X | postman-collection |
Postman no parece estar «estructurado» para integrar librerías externas en su ecosistema. Las alternativas para hacerlo son básicamente dos:
- A través de scripts, descargar la librería desde un CDN y ejecutar la función eval en la cadena de texto devuelta. Dependiendo de dónde se coloque esta llamada, la librería se descarga en cada ejecución de solicitud o prueba.
- Colocar el código fuente de la librería en una variable a nivel de colección (o entorno) e invocar una “función anónima” para acceder a sus métodos.
Sin duda, es más fácil hacerlo que decirlo, pero, en mi opinión, es un poco complejo.
En Bruno, las cosas son mucho más simples: lo primero que hay que hacer es crear el archivo package.json con las librerías que queremos incluir y colocarlo en la raíz de nuestro proyecto:
Luego, como si fuera cualquier proyecto NodeJS, instalamos las dependencias:
npm install
A partir de este momento, las librerías estarán a nuestra disposición y podremos usarlas en cualquier parte dentro de nuestra colección.
Scripting
Bruno, al igual que Postman, ofrece la posibilidad de personalizar las llamadas en los siguientes eventos:
- Pre-Request
- Post-Response
Cada uno de estos eventos puede ser personalizado a nivel de solicitud individual (y por lo tanto enfocado en una sola solicitud) o a nivel de colección (y por lo tanto con efecto en todas las solicitudes subyacentes).
Las razones para introducir scripting son variadas, desde la precompilación de variables de una solicitud/colección hasta la generación de un JWT para la autenticación, sin olvidar el procesamiento de las respuestas obtenidas de las llamadas y muchas otras posibilidades.
En el contexto del scripting, Bruno pone a disposición tres variables fundamentales:
- req: Representa la solicitud.
- res: Representa la respuesta.
- bru: Expone métodos que nos permiten interactuar con Bruno y su ecosistema.
En la sección «Pre Request» podemos forzar las características de la solicitud, configurando variables a nivel de colección o entorno, e incluso el método o la URL de la solicitud.
Bruno nos permite «ocultar» los valores de nuestros secretos, colocándolos en un archivo .env guardado dentro de nuestro directorio de trabajo. Para evitar que este archivo sea público en nuestro control de versiones, debemos incluirlo en nuestro archivo .gitignore (para beneficio de nuestros colaboradores, podemos crear un archivo .env.example que contenga valores ficticios para indicarles cómo crear su propio archivo .env).
Podemos, entonces, extraer valores de nuestros secretos, generar datos aleatorios usando librerías externas y, por qué no, establecer valores devueltos por llamadas a otros servicios.
Por ejemplo, podemos extraer el valor secretísimo «MySecretValue» del archivo de entorno actual para colocarlo tanto en un encabezado (X-Secret) como en una variable:
También podemos definir variables sin necesidad de pasar por un script, utilizando la interfaz de usuario declarativa:
Lo que acabamos de definir se puede usar en el cuerpo de la solicitud, aprovechando la sintaxis del sistema de plantillas de Bruno:
Después de ejecutar la solicitud, podemos verificar los parámetros en la pestaña «Timeline» de la interfaz de usuario, donde podemos confirmar el encabezado configurado por el script (X-Secret) y el cuerpo poblado con los valores de nuestras variables:
En este punto, el único límite que podemos tener es el de nuestra imaginación. Por ejemplo, podemos usar las librerías previamente instaladas para generar una dirección de correo electrónico (con faker) y «transformarla» en un color (con uniqolor), para enviar la solicitud a nuestro servicio de prueba:
Request Body | Response | |
=> |
Finalmente (spoiler de la próxima sección), podemos verificar, mediante Assert, que el servicio nos esté devolviendo la misma dirección de correo electrónico que hemos enviado:
Asserts Declarativos
Esta funcionalidad me ha «capturado» de inmediato, ya que simplifica enormemente la implementación de los tests más «básicos» y, al mismo tiempo, permite la libertad de implementar lógicas más complejas mediante scripts.
Al final de cada solicitud, es posible configurar tests para verificar su correcto funcionamiento basado en nuestras suposiciones.
Mientras que en Postman estamos obligados a escribir código para implementar los tests, Bruno nos ofrece la posibilidad de «declararlos», aligerando nuestro trabajo, al menos para aquellos más simples y lineales.
Intentemos, por ejemplo, escribir algunos tests para la llamada a api.chucknorris.io, que típicamente responde con un JSON similar a este:
Supongamos que queremos verificar que:
- El campo value sea efectivamente una cadena de texto.
- El campo id cumpla con una expresión regular específica.
- El estado de la respuesta sea 200 (OK).
- El campo updated_at sea efectivamente una fecha/hora.
Operando en el modo típico de Postman, habríamos escrito tests como estos (lo cual, como podemos ver, también podemos hacer en Bruno):
Aparte de algunas pequeñas diferencias sintácticas, podemos constatar que los dos sistemas son bastante similares. Pero Bruno tiene un as bajo la manga, ya que nos permite «declarar» estos tests en el panel «Assert» de nuestra solicitud:
Notamos que la simplicidad de configuración de los Assert me ha permitido verificar la validez del campo «updated_at» solo mediante una expresión regular y no utilizando la librería moment, como fue posible hacer con los scripts.
Detrás de escena, en el archivo Bru, los Assert mencionados se traducen en estas pocas líneas de configuración::
Ejecutar las Colecciones
Es normal que, durante el desarrollo de una funcionalidad, se pruebe la API específica en la que se está trabajando. Asimismo, es igualmente normal que, al finalizar el trabajo, se ejecuten todas (o casi todas) las solicitudes de una colección para verificar que no se han introducido regresiones.
En este contexto, Postman muestra uno de sus límites más odiados: el número máximo de «collection run» disponibles mensualmente, que son:
- 25 para los planes Free/Basic
- 250 para el plan Professional
- Ilimitado para el plan Enterprise
Sin entrar en el mérito de estas decisiones, notamos que Bruno no nos impone ningún límite, permitiéndonos un número ilimitado de ejecuciones: es suficiente seleccionar “Run” del menú desplegable asociado al nombre de la colección para obtener el resultado de las llamadas:
=> |
Como alternativa a la interfaz de usuario, Bruno ofrece un ejecutor de línea de comandos (CLI) que se puede instalar a través de npm:
npm install -g @usebruno/cli
A partir de este momento, tenemos a disposición nuestro ejecutor; para probarlo, abrimos un terminal y nos ubicamos en el directorio principal de nuestra colección. Las principales modalidades de ejecución son las siguientes:
- bru run: Ejecuta todas las solicitudes de la colección actual.
- bru run request.bru: Ejecuta una solicitud específica.
- bru run <folder>: Ejecuta todas las solicitudes de un directorio específico.
Modelos de Licenciamiento
Las licencias de software siempre han sido un tema delicado para las empresas, ya que a menudo se perciben como un costo (casi como un «peaje» en algunos casos) que no trae beneficios efectivos, aparte del enriquecimiento del productor (que, en cualquier caso, no vive del aire y del amor).
Bruno, con su «Golden Edition», ofrece a los usuarios algunas funcionalidades adicionales respecto a la versión Community, entre las que se incluyen:
- Bru File Explorer: La posibilidad de modificar una solicitud accediendo directamente al archivo Bru que la representa, en lugar de gestionar scripts adicionales en JavaScript. Estas operaciones también son posibles sin licencia, pero en la versión Community es necesario recurrir a editores externos.
- Visual Git: Una interfaz de usuario con la que gestionar visualmente la interacción con el control de versiones. Personalmente, soy «a la antigua» y uso la querida y vieja línea de comandos… Pero para quienes están acostumbrados a estas herramientas visuales, se trata de una integración interesante (similar a la extensión GitLens de VSCode).
- Developer Tools: Una serie (hasta ahora relativamente mínima) de herramientas para la gestión de estructuras JSON (incluye un «beautifier» y un convertidor a YAML) y de JWT (incluye un decodificador).
No olvidemos que, para Bruno, la «licencia» es principalmente sinónimo de «apoyo al desarrollo».
En cuanto a Postman, la complejidad del modelo de licenciamiento es directamente proporcional a la amplitud de la oferta: cuatro planes (Free, Basic, Professional y Enterprise) con precios mensuales crecientes basados en el número de usuarios.
El límite más importante, en mi opinión, es el relativo al número máximo de miembros del equipo, que en la versión Free está limitado a 3. Para ampliar el equipo incluso en una sola unidad es necesario pasar al menos a la versión Basic, enfrentando un costo no precisamente «insignificante».
¿Qué le falta a Bruno?
Mientras que la primera commit de Bruno data de diciembre de 2021, Postman vio la luz en 2012, ¡9 años antes! Estos años adicionales le han permitido difundirse y mejorar progresivamente, hasta convertirse, de hecho, en el estándar del sector.
Seguramente a Bruno todavía le faltan muchas cosas para ser realmente considerado al nivel de Postman, por ejemplo:
- Flows: Editor visual de flujos de llamadas API.
- Postbot: IA aplicada a la generación de llamadas API, documentación y tests.
- Mock Servers: Permiten la simulación de API a través de la devolución de datos (falsos) predefinidos.
En mi opinión, a pesar de estas «lagunas», Bruno cumple excelentemente con sus funciones, ayudando enormemente en el trabajo diario de desarrollo.
La comunidad de Bruno está en continuo crecimiento, lo que permite tener esperanzas en un futuro prometedor, lleno de nuevas ideas, características y mejoras, en beneficio del producto mismo.
Artículo recomendado: cómo encontrar proyectos de código abierto interesantes
Bruno vs Postman: Conclusiones
Nunca he sido un defensor del software «perfecto», sé muy bien que no existe. En cambio, estoy firmemente convencido de que puede existir el que mejor se adapta a nuestras necesidades.
Sin pretender tener la verdad absoluta y, sobre todo, sin la necesidad de vender nada a nadie (algo que, como técnico, no soy capaz de hacer), me permito recomendaros que deis una oportunidad a Bruno. Estoy seguro de que os gustará y, quién sabe, tal vez descubrais que es justo lo que necesitais.
Lo habéis probado? ¿Os ha resuelto algún problema? ¿Qué pensáis que no funciona o se podría mejorar?