Ir al contenido

Comandos de Bruno

Bruno es un cliente API ligero, de código abierto y nativo de Git diseñado para pruebas y desarrollo de APIs. A diferencia de Postman, Bruno almacena tus colecciones como archivos de texto plano (formato .bru) que se pueden versionar con Git, lo que lo hace ideal para colaboración en equipo e integración con pipelines CI/CD.

Instalación

PlataformaComando
macOS (Homebrew)brew install bruno
Linux (Snap)snap install bruno
Linux (APT)sudo apt-get install bruno
Windows (Chocolatey)choco install bruno
npmnpm install -g @usebruno/cli
DescargarVisita usebruno.com/downloads

Empezar

Lanzar la interfaz gráfica de Bruno

bruno

Crear una nueva colección

bruno create-collection my-api-collection

Abrir colección existente

bruno /path/to/collection

Gestión de colecciones

Estructura de colecciones

Bruno almacena colecciones como directorios con archivos .bru:

my-api-collection/
├── bruno.json          # Metadatos de colección
├── environments/
│   ├── Development.json
│   └── Production.json
├── auth/
│   └── auth.bru
└── users/
    ├── get-all-users.bru
    ├── create-user.bru
    └── update-user.bru

Importar desde Postman

# En la interfaz de Bruno: Import → Selecciona JSON de colección de Postman
# O usa CLI (si está disponible en tu versión de Bruno)

Organizar solicitudes en carpetas

Crea carpetas dentro de tu colección para organizar solicitudes:

  • Haz clic derecho en el árbol de colecciones → Nueva carpeta
  • Nombra carpetas lógicamente (ej: usuarios, productos, auth)
  • Arrastra solicitudes entre carpetas

Exportar colección

# Las colecciones se almacenan como archivos simples (formato .bru)
# Simplemente haz commit a Git o comparte el directorio

Lenguaje Bru (formato de solicitud)

Bruno usa archivos .bru—un lenguaje de marcado simple y legible para solicitudes.

Archivo de solicitud básico

meta {
  name: Get All Users
  type: http
  seq: 1
}

get {
  url: {{baseUrl}}/api/users
  auth: bearer
}

params:query {
  limit: 10
  offset: 0
}

headers {
  Content-Type: application/json
  User-Agent: Bruno/v1
}

auth:bearer {
  token: {{authToken}}
}

Solicitud con cuerpo

meta {
  name: Create User
  type: http
  seq: 2
}

post {
  url: {{baseUrl}}/api/users
}

headers {
  Content-Type: application/json
}

body:json {
  {
    "name": "John Doe",
    "email": "john@example.com",
    "role": "admin"
  }
}

Solicitud de datos de formulario

meta {
  name: Upload Profile Picture
  type: http
  seq: 3
}

post {
  url: {{baseUrl}}/api/users/{{userId}}/avatar
}

body:form-urlencoded {
  username: johndoe
  email: john@example.com
}

Multipart de formulario (carga de archivo)

meta {
  name: Upload File
  type: http
  seq: 4
}

post {
  url: {{baseUrl}}/api/files/upload
}

body:multipartForm {
  file: @/path/to/file.pdf
  description: My document
}

Comandos CLI

Ejecutar colección o solicitud

# Ejecutar colección completa
bru run /path/to/collection

# Ejecutar solicitud específica
bru run /path/to/collection/requests/get-users.bru

# Ejecutar con entorno específico
bru run /path/to/collection --env Production

# Ejecutar con formato de reporte JSON
bru run /path/to/collection --reporter json

# Ejecutar con reporte HTML
bru run /path/to/collection --reporter html --output report.html

Reporteros disponibles

ReporteroComando
CLI (predeterminado)bru run collection --reporter cli
JSONbru run collection --reporter json
HTMLbru run collection --reporter html --output report.html
JUnitbru run collection --reporter junit

Ejecutar con variables

# Pasar variables de entorno
bru run /path/to/collection --env Development

# Sobrescribir variable específica
bru run /path/to/collection --env Production --variable apiKey=abc123

Fallar en error

# Salir con estado no cero si alguna prueba falla (útil para CI/CD)
bru run /path/to/collection --failOnError

Salida detallada

# Mostrar información detallada de solicitud/respuesta
bru run /path/to/collection --verbose

Variables de entorno

Crear archivo de entorno

Los archivos de entorno se almacenan como environments/EnvName.json:

{
  "baseUrl": "https://api.example.com",
  "apiKey": "your-api-key-here",
  "authToken": "bearer-token",
  "userId": "12345",
  "timeout": 5000
}

Usar variables en solicitudes

get {
  url: {{baseUrl}}/api/users/{{userId}}
  timeout: {{timeout}}
}

headers {
  Authorization: Bearer {{authToken}}
  X-API-Key: {{apiKey}}
}

Cambiar entornos

# Vía CLI
bru run /path/to/collection --env Development

# Vía interfaz gráfica: Selecciona entorno en dropdown de Bruno

Tipos de variables de entorno

TipoEjemploUso
Cadena"apiKey": "abc123"{{apiKey}}
Número"timeout": 5000{{timeout}}
Booleano"debug": true{{debug}}
Objeto"config": {...}Acceso con scripts

Gestión de secretos

# Crear archivo .env para datos sensibles (agregar a .gitignore)
echo "PROD_API_KEY=secret123" > .env

# Usar en archivo de entorno con referencia
# O usar interfaz de Bruno para marcar campos como "Secreto"

Scripts previos a la solicitud

Agrega JavaScript antes de que se envíe la solicitud:

// Establecer valores dinámicos
bru.setEnvVar('timestamp', Date.now());
bru.setEnvVar('nonce', Math.random().toString(36).substring(7));

// Lógica condicional
if (bru.getEnvVar('env') === 'production') {
  bru.setEnvVar('timeout', 10000);
}

// Registrar información de depuración
console.log('Sending request to', bru.getEnvVar('baseUrl'));

Scripts posteriores a la respuesta

Ejecuta JavaScript después de recibir la respuesta:

// Acceder a datos de respuesta
const responseData = res.getBody();
const statusCode = res.getStatus();
const headers = res.getHeaders();

// Guardar valores para siguiente solicitud
if (statusCode === 200) {
  bru.setEnvVar('authToken', responseData.token);
  bru.setEnvVar('userId', responseData.user.id);
}

// Registrar respuesta
console.log('Status:', statusCode);
console.log('Response:', JSON.stringify(responseData, null, 2));

Operaciones comunes de respuesta

// Obtener código de estado
const status = res.getStatus();

// Obtener cuerpo como cadena
const body = res.getBody();

// Analizar cuerpo JSON
const data = res.getBody(true); // true = analizar como JSON

// Obtener encabezados
const contentType = res.getHeader('content-type');

// Obtener encabezado específico
const authHeader = res.getHeader('authorization');

Aserciones y pruebas

Aserciones de prueba integradas

// Aserción de código de estado
tests['Status is 200'] = (res.getStatus() === 200);

// El cuerpo de respuesta contiene
tests['Response contains user'] = res.getBody().includes('john');

// Validación de respuesta JSON
const data = res.getBody(true);
tests['User ID exists'] = data.user && data.user.id > 0;

// Tiempo de respuesta
tests['Response time < 500ms'] = res.getResponseTime() < 500;

// Validación de encabezado
tests['Content-Type is JSON'] = res.getHeader('content-type').includes('application/json');

Ejemplo de prueba compleja

const data = res.getBody(true);

tests['Status is 201'] = res.getStatus() === 201;
tests['ID is a number'] = typeof data.id === 'number';
tests['Email is valid'] = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(data.email);
tests['Created at is ISO date'] = !isNaN(Date.parse(data.createdAt));

// Guardar para siguiente solicitud
if (tests['Status is 201']) {
  bru.setEnvVar('newUserId', data.id);
}

Autenticación

Token portador

auth:bearer {
  token: {{authToken}}
}

Autenticación básica

auth:basic {
  username: {{username}}
  password: {{password}}
}

Clave de API (encabezado)

headers {
  X-API-Key: {{apiKey}}
  Authorization: ApiKey {{apiKey}}
}

Clave de API (parámetro de consulta)

params:query {
  api_key: {{apiKey}}
  apiToken: {{token}}
}

OAuth 2.0

auth:oauth2 {
  grant_type: authorization_code
  authorization_url: https://provider.com/oauth/authorize
  token_url: https://provider.com/oauth/token
  client_id: {{clientId}}
  client_secret: {{clientSecret}}
  scope: read write
}

Autenticación de resumen

auth:digest {
  username: {{username}}
  password: {{password}}
}

Tipos de solicitud y métodos

Solicitud GET

meta {
  name: Fetch User
  type: http
  seq: 1
}

get {
  url: {{baseUrl}}/api/users/{{userId}}
}

params:query {
  includeProfile: true
  fields: id,name,email
}

Solicitud POST

post {
  url: {{baseUrl}}/api/users
}

body:json {
  {
    "name": "Jane Doe",
    "email": "jane@example.com"
  }
}

Solicitud PUT/PATCH

put {
  url: {{baseUrl}}/api/users/{{userId}}
}

body:json {
  {
    "name": "Jane Smith",
    "status": "active"
  }
}

Solicitud DELETE

delete {
  url: {{baseUrl}}/api/users/{{userId}}
}

Solicitud con encabezados

headers {
  Content-Type: application/json
  Accept: application/json
  User-Agent: Bruno/v1.0
  X-Request-ID: {{requestId}}
  Authorization: Bearer {{token}}
}

Características avanzadas

Variables a nivel de colección

Define variables en bruno.json:

{
  "name": "My API Collection",
  "version": "1.0",
  "variables": {
    "baseUrl": "https://api.example.com",
    "version": "v1",
    "defaultTimeout": 5000
  }
}

Secuenciación de solicitudes

Controla el orden de ejecución de solicitudes en CLI runner:

meta {
  name: Authenticate
  type: http
  seq: 1
}
meta {
  name: Get User Data
  type: http
  seq: 2
}

Las solicitudes se ejecutan en orden de seq.

Consultas GraphQL

meta {
  name: GraphQL Query
  type: http
  seq: 1
}

post {
  url: {{baseUrl}}/graphql
}

body:graphql {
  query {
    user(id: "{{userId}}") {
      id
      name
      email
    }
  }
}

Parámetros de consulta

params:query {
  page: 1
  limit: 10
  sort: -createdAt
  filter: status:active
}

Flujo de trabajo de Git

Por qué nativo de Git es importante

# Las colecciones se almacenan como archivos de texto
.bru/
├── users/
   ├── get-user.bru
   └── create-user.bru
└── products/
    └── list-products.bru

# Fácil de controlar versiones
git add .
git commit -m "Update API requests"
git push origin main

# Los conflictos de fusión son manejables
# Revisa cambios en PRs
# Colabora con el equipo

Flujo de trabajo de colaboración

# Miembro del equipo clona colección
git clone https://github.com/team/api-collection.git
cd api-collection

# Instala Bruno CLI
npm install -g @usebruno/cli

# Ejecuta pruebas localmente
bru run . --env Development

# Realiza cambios
# Agrega nuevas solicitudes o actualiza existentes

# Haz commit y push
git add .
git commit -m "Add payment API endpoints"
git push origin feature/payments

Ignorar archivos sensibles

# .gitignore en raíz de colección
.env
.env.local
environments/Production.json
!environments/Production.json.example
secrets/
node_modules/

Integración CI/CD

GitHub Actions

name: API Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install 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 . --env CI --reporter json --output test-results.json

      - name: Upload results
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: test-results
          path: test-results.json

GitLab CI

api-tests:
  image: node:18
  script:
    - npm install -g @usebruno/cli
    - bru run . --env CI --reporter json --output test-results.json
  artifacts:
    paths:
      - test-results.json
    reports:
      junit: test-results.json

Hook de pre-commit local

#!/bin/bash
# .git/hooks/pre-commit

echo "Running API tests..."
bru run . --env Development --failOnError

if [ $? -ne 0 ]; then
  echo "API tests failed. Commit aborted."
  exit 1
fi

Flujos de trabajo comunes

Prueba de API REST

# 1. Configurar entorno
bru run /path/to/collection --env Development

# 2. Verificar resultados de prueba
# Las pruebas muestran aprobado/fallido en salida

# 3. Generar reporte
bru run /path/to/collection --env Development --reporter html --output report.html

Pruebas de carga con solicitudes paralelas

// En script previo a solicitud
for (let i = 0; i < 10; i++) {
  bru.setEnvVar('iteration', i);
}

Generación de datos dinámicos

// Generar email único por solicitud
const timestamp = Date.now();
bru.setEnvVar('dynamicEmail', `user_${timestamp}@example.com`);

// Generar ID aleatorio
bru.setEnvVar('randomId', Math.floor(Math.random() * 10000));

Encadenamiento de solicitudes

// En script posterior a respuesta de primera solicitud
const data = res.getBody(true);
bru.setEnvVar('userId', data.id);
// Siguiente solicitud usa {{userId}}

Depuración

Habilitar modo detallado

bru run /path/to/collection --verbose

Ver detalles de solicitud/respuesta

En la interfaz gráfica de Bruno:

  • Haz clic en solicitud
  • Ver pestaña “Params” para parámetros de consulta
  • Ver pestaña “Body” para cuerpo de solicitud
  • Ver pestaña “Response” para datos de respuesta
  • Ver pestaña “Tests” para resultados de prueba

Registro en consola

// En scripts previos a solicitud o posteriores a respuesta
console.log('Variable value:', bru.getEnvVar('baseUrl'));
console.log('Full response:', res.getBody());
console.log('Status code:', res.getStatus());

Inspección de red

// Verificar encabezados de respuesta
const headers = res.getHeaders();
console.log('All headers:', headers);

// Verificar tiempo de respuesta
console.log('Response time:', res.getResponseTime(), 'ms');

Mejores prácticas de estructura de archivos

api-collection/
├── README.md                 # Documentación
├── .gitignore               # Ignorar archivos sensibles
├── bruno.json               # Metadatos de colección
├── environments/            # Archivos de entorno
│   ├── Development.json
│   ├── Staging.json
│   └── Production.json
├── globals.json             # Variables globales
├── auth/
│   ├── login.bru
│   └── refresh-token.bru
├── users/
│   ├── get-all-users.bru
│   ├── get-user-by-id.bru
│   ├── create-user.bru
│   ├── update-user.bru
│   └── delete-user.bru
├── products/
│   ├── list-products.bru
│   └── get-product.bru
└── scripts/
    ├── test-runner.js
    └── helpers.js

Recursos

RecursoURL
Sitio web oficialusebruno.com
Repositorio GitHubgithub.com/usebruno/bruno
Documentacióndocs.usebruno.com
Descargarusebruno.com/downloads
Comunidad Discorddiscord.gg/usebruno
Especificación lenguaje Brugithub.com/usebruno/bru
Guía de pruebas de APIdocs.usebruno.com/api-testing
Problemas de GitHubgithub.com/usebruno/bruno/issues

Consejos y trucos

  • Git Diff para revisiones: Como las colecciones son archivos, usa git diff para revisar cambios de API antes de fusionar
  • Plantillas de entorno: Crea archivos .example.json para entornos para compartir estructura de configuración sin secretos
  • Scripts reutilizables: Almacena scripts de prueba comunes en archivos .js separados y referénciálos
  • Alcance de variable: Las variables de colección se aplican globalmente; las variables a nivel de solicitud las sobrescriben
  • Rendimiento: Usa bandera --failOnError en CI/CD para detectar fallos de prueba temprano
  • Documentación: Agrega comentarios en archivos .bru usando sintaxis // comment
  • Versionamiento: Incluye versión de API en variable de URL base para cambiar fácilmente entre versiones