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
| Plateforme | Commande |
|---|---|
| macOS (Homebrew) | brew install bruno |
| Linux (Snap) | snap install bruno |
| Linux (APT) | sudo apt-get install bruno |
| Windows (Chocolatey) | choco install bruno |
| npm | npm install -g @usebruno/cli |
| Télécharger | Visitez 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
| Rapporteur | Commande |
|---|---|
| CLI (défaut) | bru run collection --reporter cli |
| JSON | bru run collection --reporter json |
| HTML | bru run collection --reporter html --output report.html |
| JUnit | bru 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
| Type | Exemple | Utilisation |
|---|---|---|
| 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
| Ressource | URL |
|---|---|
| Site officiel | usebruno.com |
| Référentiel GitHub | github.com/usebruno/bruno |
| Documentation | docs.usebruno.com |
| Télécharger | usebruno.com/downloads |
| Communauté Discord | discord.gg/usebruno |
| Spécification du langage Bru | github.com/usebruno/bru |
| Guide de test API | docs.usebruno.com/api-testing |
| Problèmes GitHub | github.com/usebruno/bruno/issues |
Astuces et trucs
- Diff Git pour les révisions : Puisque les collections sont des fichiers, utiliser
git diffpour examiner les modifications API avant la fusion - Modèles d’environnement : Créer des fichiers
.example.jsonpour les environnements afin de partager la structure de configuration sans secrets - Scripts réutilisables : Stocker les scripts de test courants dans des fichiers
.jssé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
--failOnErrordans CI/CD pour détecter les défaillances de test tôt - Documentation : Ajouter des commentaires dans les fichiers
.bruen 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