Aller au contenu

Commandes Bruno

Bruno est un client API léger, open-source et natif Git conçu pour tester et développer des API. Contrairement à Postman, Bruno stocke vos collections en tant que fichiers en texte brut (format .bru) qui peuvent être versionnés avec Git, ce qui le rend idéal pour la collaboration en équipe et les pipelines CI/CD.

Installation

PlateformeCommande
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
TéléchargerVisitez usebruno.com/downloads

Démarrage

Lancer l’interface graphique Bruno

bruno

Créer une nouvelle collection

bruno create-collection my-api-collection

Ouvrir une collection existante

bruno /path/to/collection

Gestion des collections

Structure de collection

Bruno stocke les collections en tant que répertoires avec des fichiers .bru :

my-api-collection/
├── bruno.json          # Métadonnées de collection
├── environments/
│   ├── Development.json
│   └── Production.json
├── auth/
│   └── auth.bru
└── users/
    ├── get-all-users.bru
    ├── create-user.bru
    └── update-user.bru

Importer depuis Postman

# Dans l'interface graphique Bruno : Importer → Sélectionner la collection JSON de Postman
# Ou utiliser la CLI (si disponible pour votre version de Bruno)

Organiser les requêtes dans les dossiers

Créez des dossiers dans votre collection pour organiser les requêtes :

  • Clic droit dans l’arborescence de la collection → Nouveau dossier
  • Nommer les dossiers de manière logique (par exemple, users, products, auth)
  • Faire glisser les requêtes entre les dossiers

Exporter la collection

# Les collections sont stockées en tant que fichiers bruts (format .bru)
# Il suffit de valider sur Git ou partager le répertoire

Langage Bru (format de requête)

Bruno utilise les fichiers .bru—un langage de balisage simple et lisible pour les requêtes.

Fichier de requête basique

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}}
}

Requête avec corps

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"
  }
}

Requête de données de formulaire

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
}

Formulaire multipart (téléchargement de fichier)

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

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

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

Commandes CLI

Exécuter une collection ou une requête

# Exécuter la collection complète
bru run /path/to/collection

# Exécuter une requête spécifique
bru run /path/to/collection/requests/get-users.bru

# Exécuter avec un environnement spécifique
bru run /path/to/collection --env Production

# Exécuter avec format de rapport JSON
bru run /path/to/collection --reporter json

# Exécuter avec rapport HTML
bru run /path/to/collection --reporter html --output report.html

Rapporteurs disponibles

RapporteurCommande
CLI (défaut)bru run collection --reporter cli
JSONbru run collection --reporter json
HTMLbru run collection --reporter html --output report.html
JUnitbru run collection --reporter junit

Exécuter avec des variables

# Passer des variables d'environnement
bru run /path/to/collection --env Development

# Remplacer une variable spécifique
bru run /path/to/collection --env Production --variable apiKey=abc123

Échouer en cas d’erreur

# Quitter avec un statut non zéro si un test échoue (utile pour CI/CD)
bru run /path/to/collection --failOnError

Sortie détaillée

# Afficher les informations détaillées des requêtes/réponses
bru run /path/to/collection --verbose

Variables d’environnement

Créer un fichier d’environnement

Les fichiers d’environnement sont stockés en tant que environments/EnvName.json :

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

Utiliser des variables dans les requêtes

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

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

Basculer les environnements

# Via CLI
bru run /path/to/collection --env Development

# Via interface graphique : Sélectionner le déroulant d'environnement dans Bruno

Types de variables d’environnement

TypeExempleUtilisation
Chaîne de caractères"apiKey": "abc123"{{apiKey}}
Nombre"timeout": 5000{{timeout}}
Booléen"debug": true{{debug}}
Objet"config": {...}Accès avec scripts

Gestion des secrets

# Créer un fichier .env pour les données sensibles (ajouter à .gitignore)
echo "PROD_API_KEY=secret123" > .env

# Utiliser dans le fichier d'environnement avec référence
# Ou utiliser l'interface graphique Bruno pour marquer les champs comme "Secret"

Scripts de pré-requête

Ajouter du JavaScript avant l’envoi de la requête :

// Définir des valeurs dynamiques
bru.setEnvVar('timestamp', Date.now());
bru.setEnvVar('nonce', Math.random().toString(36).substring(7));

// Logique conditionnelle
if (bru.getEnvVar('env') === 'production') {
  bru.setEnvVar('timeout', 10000);
}

// Informations de débogage du journal
console.log('Sending request to', bru.getEnvVar('baseUrl'));

Scripts de post-réponse

Exécuter du JavaScript après réception de la réponse :

// Accéder aux données de réponse
const responseData = res.getBody();
const statusCode = res.getStatus();
const headers = res.getHeaders();

// Enregistrer les valeurs pour la requête suivante
if (statusCode === 200) {
  bru.setEnvVar('authToken', responseData.token);
  bru.setEnvVar('userId', responseData.user.id);
}

// Journal des réponses
console.log('Status:', statusCode);
console.log('Response:', JSON.stringify(responseData, null, 2));

Opérations de réponse courantes

// Obtenir le code de statut
const status = res.getStatus();

// Obtenir le corps en tant que chaîne de caractères
const body = res.getBody();

// Analyser le corps JSON
const data = res.getBody(true); // true = analyser comme JSON

// Obtenir les en-têtes
const contentType = res.getHeader('content-type');

// Obtenir un en-tête spécifique
const authHeader = res.getHeader('authorization');

Assertions et tests

Assertions de test intégrées

// Assertion du code de statut
tests['Status is 200'] = (res.getStatus() === 200);

// Le corps de réponse contient
tests['Response contains user'] = res.getBody().includes('john');

// Validation de la réponse JSON
const data = res.getBody(true);
tests['User ID exists'] = data.user && data.user.id > 0;

// Temps de réponse
tests['Response time < 500ms'] = res.getResponseTime() < 500;

// Validation d'en-tête
tests['Content-Type is JSON'] = res.getHeader('content-type').includes('application/json');

Exemple de test complexe

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));

// Enregistrer pour la requête suivante
if (tests['Status is 201']) {
  bru.setEnvVar('newUserId', data.id);
}

Authentification

Token porteur

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

Authentification basique

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

Clé API (en-tête)

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

Clé API (paramètre de requête)

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
}

Authentification Digest

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

Types et méthodes de requête

Requête GET

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

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

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

Requête POST

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

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

Requête PUT/PATCH

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

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

Requête DELETE

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

Requête avec en-têtes

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

Fonctionnalités avancées

Variables au niveau de la collection

Définir les variables dans bruno.json :

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

Séquençage des requêtes

Contrôler l’ordre d’exécution des requêtes dans le gestionnaire CLI :

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

Les requêtes s’exécutent dans l’ordre seq.

Requêtes GraphQL

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

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

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

Paramètres de requête

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

Flux de travail Git

Pourquoi l’approche Git-Native est importante

# Les collections sont stockées en tant que fichiers texte
.bru/
├── users/
   ├── get-user.bru
   └── create-user.bru
└── products/
    └── list-products.bru

# Facile à mettre en version
git add .
git commit -m "Update API requests"
git push origin main

# Les conflits de fusion sont gérables
# Examiner les modifications dans les requêtes de fusion
# Collaborer avec l'équipe

Flux de travail de collaboration

# Un membre de l'équipe clone la collection
git clone https://github.com/team/api-collection.git
cd api-collection

# Installer la CLI Bruno
npm install -g @usebruno/cli

# Exécuter les tests localement
bru run . --env Development

# Faire des modifications
# Ajouter de nouvelles requêtes ou mettre à jour les existantes

# Valider et pousser
git add .
git commit -m "Add payment API endpoints"
git push origin feature/payments

Ignorer les fichiers sensibles

# .gitignore dans la racine de la collection
.env
.env.local
environments/Production.json
!environments/Production.json.example
secrets/
node_modules/

Intégration CI/CD

Actions GitHub

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

Crochet de pré-validation 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

Flux de travail courants

Test d’API REST

# 1. Configurer l'environnement
bru run /path/to/collection --env Development

# 2. Vérifier les résultats des tests
# Les tests réussis/échoués sont affichés dans la sortie

# 3. Générer un rapport
bru run /path/to/collection --env Development --reporter html --output report.html

Test de charge avec requêtes parallèles

// Dans le script de pré-requête
for (let i = 0; i < 10; i++) {
  bru.setEnvVar('iteration', i);
}

Génération de données dynamiques

// Générer un e-mail unique par requête
const timestamp = Date.now();
bru.setEnvVar('dynamicEmail', `user_${timestamp}@example.com`);

// Générer un ID aléatoire
bru.setEnvVar('randomId', Math.floor(Math.random() * 10000));

Chaînage des requêtes

// Dans le script de post-réponse de la première requête
const data = res.getBody(true);
bru.setEnvVar('userId', data.id);
// La requête suivante utilise {{userId}}

Débogage

Activer le mode détaillé

bru run /path/to/collection --verbose

Voir les détails des requêtes/réponses

Dans l’interface graphique Bruno :

  • Cliquer sur la requête
  • Voir l’onglet “Params” pour les paramètres de requête
  • Voir l’onglet “Body” pour le corps de la requête
  • Voir l’onglet “Response” pour les données de réponse
  • Voir l’onglet “Tests” pour les résultats des tests

Journalisation sur la console

// Dans les scripts de pré-requête ou de post-réponse
console.log('Variable value:', bru.getEnvVar('baseUrl'));
console.log('Full response:', res.getBody());
console.log('Status code:', res.getStatus());

Inspection du réseau

// Vérifier les en-têtes de réponse
const headers = res.getHeaders();
console.log('All headers:', headers);

// Vérifier le temps de réponse
console.log('Response time:', res.getResponseTime(), 'ms');

Bonnes pratiques de structure de fichier

api-collection/
├── README.md                 # Documentation
├── .gitignore               # Ignorer les fichiers sensibles
├── bruno.json               # Métadonnées de collection
├── environments/            # Fichiers d'environnement
│   ├── 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

Ressources

RessourceURL
Site officielusebruno.com
Référentiel GitHubgithub.com/usebruno/bruno
Documentationdocs.usebruno.com
Téléchargerusebruno.com/downloads
Communauté Discorddiscord.gg/usebruno
Spécification du langage Brugithub.com/usebruno/bru
Guide de test APIdocs.usebruno.com/api-testing
Problèmes GitHubgithub.com/usebruno/bruno/issues

Astuces et trucs

  • Diff Git pour les révisions : Puisque les collections sont des fichiers, utiliser git diff pour examiner les modifications API avant la fusion
  • Modèles d’environnement : Créer des fichiers .example.json pour les environnements afin de partager la structure de configuration sans secrets
  • Scripts réutilisables : Stocker les scripts de test courants dans des fichiers .js séparés et les référencer
  • Portée des variables : Les variables de collection s’appliquent globalement ; les variables au niveau des requêtes les remplacent
  • Performance : Utiliser l’indicateur --failOnError dans CI/CD pour détecter les défaillances de test tôt
  • Documentation : Ajouter des commentaires dans les fichiers .bru en utilisant la syntaxe // comment
  • Contrôle de version : Inclure la version de l’API dans la variable d’URL de base pour basculer facilement entre les versions