Introducción a Bruno API Client
Bruno es un revolucionario cliente API de código abierto que adopta un enfoque fundamentalmente diferente para el testing y desarrollo de APIs. A diferencia de las herramientas tradicionales basadas en la nube, Bruno almacena colecciones directamente en tu sistema de archivos usando lenguaje de marcado de texto plano, haciéndolo verdaderamente compatible con Git y enfocado en la privacidad. Esta arquitectura basada en archivos elimina el vendor lock-in y permite colaboración fluida a través de sistemas de control de versiones.
Lanzado en 2022, Bruno rápidamente ganó tracción entre desarrolladores frustrados con modelos de precios por suscripción y dependencia de la nube. Es particularmente atractivo para equipos que ya usan flujos de trabajo Git y desarrolladores que valoran la soberanía de datos.
Por Qué Bruno Destaca
Filosofía Central y Ventajas
Arquitectura Offline-First Bruno no requiere sincronización en la nube ni cuentas. Todo se ejecuta localmente:
- No requiere login
- Privacidad completa
- Funciona sin conexión a internet
- Rápido y responsivo
Flujo de Trabajo Nativo de Git
Las colecciones son archivos de texto plano (formato .bru
) que se integran perfectamente con Git:
- Control de versiones incorporado
- Revisiones de código fáciles para cambios de API
- Desarrollo basado en branches
- Resolución de conflictos de merge usando herramientas Git estándar
Open Source y Gratuito Licenciado bajo MIT, Bruno es verdaderamente gratuito sin limitaciones artificiales:
- Sin tiers pagos ni características premium
- Desarrollo impulsado por la comunidad
- Roadmap transparente
- Arquitectura extensible
Colecciones como Código
El formato de archivo .bru
es legible por humanos y diseñado para desarrolladores:
meta {
name: Get User
type: http
seq: 1
}
get {
url: {{base_url}}/api/users/{{user_id}}
}
headers {
Authorization: Bearer {{token}}
Content-Type: application/json
}
vars:pre-request {
user_id: 123
}
tests {
test("Status code is 200", function() {
expect(res.status).to.equal(200);
});
test("Response has user data", function() {
expect(res.body).to.have.property('id');
expect(res.body).to.have.property('name');
});
}
Comenzando con Bruno
Instalación
Bruno está disponible para todas las plataformas principales:
# macOS (Homebrew)
brew install bruno
# Windows (Chocolatey)
choco install bruno
# Linux (Snap)
snap install bruno
# O descarga desde GitHub releases
# https://github.com/usebruno/bruno/releases
Creando Tu Primera Colección
- Crear Nueva Colección: File → New Collection
- Elegir Ubicación: Selecciona una carpeta en tu repositorio Git
- Agregar Environment: Crea archivos de entorno para diferentes configuraciones
- Crear Requests: Clic derecho en colección → New Request
Estructura de Directorio
my-api/
├── bruno.json # Metadata de colección
├── environments/
│ ├── local.bru
│ ├── staging.bru
│ └── production.bru
└── requests/
├── auth/
│ ├── login.bru
│ └── refresh.bru
└── users/
├── get-user.bru
├── create-user.bru
└── update-user.bru
Entendiendo el Formato .bru
El formato .bru
es intuitivo y expresivo:
meta {
name: Create User
type: http
seq: 2
}
post {
url: {{base_url}}/api/users
}
headers {
Authorization: Bearer {{access_token}}
Content-Type: application/json
}
body:json {
{
"name": "{{user_name}}",
"email": "{{user_email}}",
"role": "developer"
}
}
vars:pre-request {
user_name: John Doe
user_email: john@example.com
}
script:pre-request {
// Generar timestamp
bru.setVar("timestamp", Date.now());
// Establecer header personalizado
req.setHeader("X-Request-ID", bru.getVar("request_id"));
}
script:post-response {
// Guardar user ID para requests subsecuentes
const userId = res.body.id;
bru.setEnvVar("created_user_id", userId);
// Log response time
console.log("Response time:", res.responseTime, "ms");
}
tests {
test("User created successfully", function() {
expect(res.status).to.equal(201);
expect(res.body.id).to.be.a('number');
});
}
Gestión de Entornos
Archivos de Entorno
Los entornos de Bruno son archivos .bru
simples:
local.bru
vars {
base_url: http://localhost:3000
api_key: local-dev-key
debug: true
}
production.bru
vars {
base_url: https://api.production.com
api_key: {{process.env.PROD_API_KEY}}
rate_limit: 1000
}
Gestión de Secretos
Bruno se integra con variables de entorno del sistema para datos sensibles:
vars {
database_url: {{process.env.DATABASE_URL}}
stripe_key: {{process.env.STRIPE_SECRET_KEY}}
}
Esto previene que los secretos sean commiteados a Git mientras se mantiene la funcionalidad.
Características Avanzadas
Scripting y Automatización
Bruno soporta JavaScript en scripts pre-request y post-response:
Pre-Request Script
// Generar firma HMAC
const crypto = require('crypto');
const message = req.getBody();
const secret = bru.getEnvVar('api_secret');
const signature = crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
req.setHeader('X-Signature', signature);
Post-Response Script
// Extraer y guardar token de paginación
if (res.body.next_page_token) {
bru.setVar('page_token', res.body.next_page_token);
}
// Lógica condicional
if (res.status === 401) {
// Token expirado, trigger refresh
console.log('Refreshing authentication token...');
}
Framework de Testing Incorporado
Bruno incluye assertions estilo Chai:
tests {
// Assertions de código de estado
test("Request successful", function() {
expect(res.status).to.be.oneOf([200, 201, 204]);
});
// Validación de tiempo de respuesta
test("Response time acceptable", function() {
expect(res.responseTime).to.be.below(500);
});
// Validación de esquema JSON
test("Valid user object", function() {
expect(res.body).to.have.all.keys('id', 'name', 'email');
expect(res.body.id).to.be.a('number');
expect(res.body.email).to.match(/.+@.+\..+/);
});
// Validación de header
test("Correct content type", function() {
expect(res.headers['content-type']).to.include('application/json');
});
}
Colaboración en Colecciones
Flujo de Trabajo Basado en Git
- Commitear cambios de API junto con cambios de código
- Crear pull requests para modificaciones de API
- Revisar cambios usando herramientas Git diff estándar
- Conflictos de merge resueltos con editor de texto
Ejemplo de Flujo de Trabajo Git
# Crear feature branch
git checkout -b feature/add-user-endpoints
# Hacer cambios de API en Bruno
# Commitear cambios
git add requests/users/
git commit -m "Add user CRUD endpoints"
# Push y crear PR
git push origin feature/add-user-endpoints
Code Review de Cambios de API
+ post {
+ url: {{base_url}}/api/users
+ }
+
+ body:json {
+ {
+ "name": "{{user_name}}",
+ "email": "{{user_email}}"
+ }
+ }
Migración desde Postman
Proceso de Importación
Bruno soporta importar colecciones Postman. Si estás evaluando diferentes herramientas de testing de API y comparando sus características, la capacidad de importación de Bruno hace que el cambio sea fluido:
- Exportar desde Postman: Collection → Export → Collection v2.1
- Importar a Bruno: Collection → Import → Select Postman JSON
- Revisar mapeo: Verificar variables de entorno y scripts
- Ajustar diferencias: Modificar scripts si es necesario
Diferencias Clave a Entender
Característica | Postman | Bruno |
---|---|---|
Almacenamiento | Cloud | Sistema de archivos |
Formato | JSON | .bru (texto) |
Sync | Automático | Git |
Precio | Freemium | Gratis |
Colaboración | Incorporada | Basada en Git |
Scripts | Sandbox Postman | Módulos Node.js |
Workspaces | Cloud workspaces | Carpetas |
Migración de Scripts
Script de Postman
pm.environment.set("token", pm.response.json().access_token);
pm.test("Status is 200", () => {
pm.response.to.have.status(200);
});
Equivalente en Bruno
bru.setEnvVar("token", res.body.access_token);
test("Status is 200", function() {
expect(res.status).to.equal(200);
});
CLI y Automatización
Bruno CLI
Ejecuta colecciones desde línea de comandos:
# Instalar CLI
npm install -g @usebruno/cli
# Ejecutar colección completa
bru run --collection ./my-api
# Ejecutar carpeta específica
bru run --collection ./my-api --folder users
# Usar entorno específico
bru run --collection ./my-api --env production
# Formatos de output
bru run --collection ./my-api --output junit.xml --format junit
Integración CI/CD
Ejemplo GitHub Actions
name: API Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Bruno CLI
run: npm install -g @usebruno/cli
- name: Run API Tests
run: bru run --collection ./api-tests --env ci
env:
API_KEY: ${{ secrets.API_KEY }}
BASE_URL: ${{ secrets.BASE_URL }}
- name: Upload Results
uses: actions/upload-artifact@v3
with:
name: test-results
path: test-results.xml
Ejemplo GitLab CI
api-tests:
stage: test
image: node:18
script:
- npm install -g @usebruno/cli
- bru run --collection ./api-tests --env staging
variables:
API_KEY: $STAGING_API_KEY
artifacts:
reports:
junit: test-results.xml
Soporte GraphQL
Bruno maneja requests GraphQL nativamente. Para equipos que trabajan con APIs gRPC, es importante notar que Bruno se enfoca principalmente en REST y GraphQL:
meta {
name: Get User Posts
type: graphql
}
post {
url: {{graphql_endpoint}}
}
body:graphql {
query GetUserPosts($userId: ID!) {
user(id: $userId) {
id
name
posts(first: 10) {
edges {
node {
id
title
publishedAt
}
}
}
}
}
}
body:graphql:vars {
{
"userId": "{{user_id}}"
}
}
headers {
Authorization: Bearer {{graphql_token}}
}
Mejores Prácticas
Organización de Colecciones
Estructura de Carpetas Lógica
api-collection/
├── 01-authentication/
│ ├── login.bru
│ ├── logout.bru
│ └── refresh-token.bru
├── 02-users/
│ ├── list-users.bru
│ ├── get-user.bru
│ ├── create-user.bru
│ ├── update-user.bru
│ └── delete-user.bru
├── 03-posts/
└── 04-admin/
Convenciones de Nomenclatura
- Usa nombres descriptivos:
create-user.bru
nouser1.bru
- Prefijo con números para ordenar:
01-login.bru
,02-get-profile.bru
- Usa kebab-case para consistencia
Control de Versiones
Configuración .gitignore
# Ignorar overrides locales de entorno
environments/local.bru
# Ignorar archivos temporales
*.tmp
.bruno-cache/
# Mantener tracked
!environments/*.example.bru
Mensajes de Commit Significativos
git commit -m "Add user registration endpoint with validation"
git commit -m "Update auth flow to use refresh tokens"
git commit -m "Fix pagination in list users endpoint"
Seguridad
Variables de Entorno para Secretos
# Production environment
vars {
base_url: https://api.example.com
# Nunca hardcodear secretos
api_key: {{process.env.PROD_API_KEY}}
db_password: {{process.env.DB_PASSWORD}}
}
Ejemplo Archivo .env (git-ignored)
PROD_API_KEY=sk_live_xxxxxxxxxxxxx
DB_PASSWORD=super_secret_password
STRIPE_KEY=sk_live_xxxxxxxxxxxxx
Solución de Problemas
Problemas Comunes
Colecciones No Cargan
- Verificar que
bruno.json
existe en raíz de colección - Verificar permisos de archivo
- Asegurar que archivos .bru usan sintaxis correcta
Variables de Entorno No Resuelven
- Verificar que el entorno está seleccionado
- Verificar spelling de nombre de variable
- Para variables
process.env
, asegurar que están exportadas
Scripts No Ejecutan
- Verificar errores de sintaxis JavaScript
- Verificar que módulos Node.js están disponibles
- Revisar output de consola para mensajes de error
Optimización de Rendimiento
Colecciones Grandes
- Dividir en múltiples colecciones
- Usar organización de carpetas
- Carga selectiva en CLI
Tiempo de Respuesta
- Monitorear condiciones de red
- Verificar configuraciones de timeout
- Usar connection pooling para requests masivos
Comparación: Bruno vs Competidores
Al elegir un cliente API, vale la pena comparar Bruno contra alternativas como Insomnia REST client:
Característica | Bruno | Postman | Insomnia | Thunder Client |
---|---|---|---|---|
Costo | Gratis | Freemium | Freemium | Gratis + Pro |
Offline | Sí | Limitado | Sí | Sí |
Almacenamiento | Archivos locales | Cloud | Híbrido | Workspace VS Code |
Compatible Git | Excelente | Pobre | Moderado | Bueno |
Colaboración | Basada en Git | Incorporada | Pago | Limitada |
Curva de Aprendizaje | Baja | Media | Baja | Muy Baja |
Extensibilidad | Scripts | Scripts + Apps | Plugins | Limitada |
Conclusión
Bruno API Client representa un cambio de paradigma en herramientas de testing de API, priorizando flujos de trabajo de desarrollador, propiedad de datos y simplicidad. Su arquitectura basada en archivos se alinea perfectamente con prácticas modernas de desarrollo centradas en Git, haciéndolo una opción ideal para equipos ya cómodos con control de versiones.
La naturaleza open-source asegura transparencia, innovación impulsada por la comunidad y libertad del vendor lock-in. Aunque puede carecer de algunas características avanzadas encontradas en herramientas establecidas como Postman, el enfoque de Bruno en funcionalidad central y experiencia del desarrollador lo hace cada vez más atractivo para equipos que buscan una alternativa liviana y enfocada en privacidad.
Ya sea que estés migrando desde Postman, comenzando de cero con testing de API, o buscando mejor integración con tu flujo de trabajo Git, Bruno ofrece una solución convincente y costo-efectiva que pone a los desarrolladores primero.