Bruno-Befehle
Bruno ist ein leichtgewichtiger, Open-Source, Git-nativer API-Client, der zum Testen und Entwickeln von APIs konzipiert ist. Im Gegensatz zu Postman werden Ihre Sammlungen als Nur-Text-Dateien (.bru-Format) gespeichert, die mit Git versioniert werden können, was es ideal für Teamzusammenarbeit und CI/CD-Pipelines macht.
Installation
| Plattform | Befehl |
|---|---|
| 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 |
| Download | Besuchen Sie usebruno.com/downloads |
Erste Schritte
Bruno GUI starten
bruno
Neue Sammlung erstellen
bruno create-collection my-api-collection
Vorhandene Sammlung öffnen
bruno /path/to/collection
Sammlungsverwaltung
Sammlungsstruktur
Bruno speichert Sammlungen als Verzeichnisse mit .bru-Dateien:
my-api-collection/
├── bruno.json # Sammlungsmetadaten
├── environments/
│ ├── Development.json
│ └── Production.json
├── auth/
│ └── auth.bru
└── users/
├── get-all-users.bru
├── create-user.bru
└── update-user.bru
Von Postman importieren
# In Bruno GUI: Import → Postman-Sammlungs-JSON auswählen
# Oder CLI verwenden (falls für Ihre Bruno-Version verfügbar)
Anfragen in Ordnern organisieren
Erstellen Sie Ordner in Ihrer Sammlung, um Anfragen zu organisieren:
- Klicken Sie mit der rechten Maustaste in den Sammlungsbaum → Neuer Ordner
- Benennen Sie Ordner logisch (z. B. users, products, auth)
- Ziehen Sie Anfragen zwischen Ordnern
Sammlung exportieren
# Sammlungen werden als Nur-Text-Dateien (.bru-Format) gespeichert
# Übertragen Sie sie einfach zu Git oder teilen Sie das Verzeichnis
Bru-Sprache (Anfrage-Format)
Bruno verwendet .bru-Dateien – eine einfache, lesbare Markup-Sprache für Anfragen.
Basis-Anfrage-Datei
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}}
}
Anfrage mit Text
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"
}
}
Formular-Daten-Anfrage
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-Formular (Datei-Upload)
meta {
name: Upload File
type: http
seq: 4
}
post {
url: {{baseUrl}}/api/files/upload
}
body:multipartForm {
file: @/path/to/file.pdf
description: My document
}
CLI-Befehle
Sammlung oder Anfrage ausführen
# Gesamte Sammlung ausführen
bru run /path/to/collection
# Spezifische Anfrage ausführen
bru run /path/to/collection/requests/get-users.bru
# Mit spezifischer Umgebung ausführen
bru run /path/to/collection --env Production
# Im JSON-Reporter-Format
bru run /path/to/collection --reporter json
# Mit HTML-Report
bru run /path/to/collection --reporter html --output report.html
Verfügbare Reporter
| Reporter | Befehl |
|---|---|
| CLI (Standard) | 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 |
Mit Variablen ausführen
# Umgebungsvariablen übergeben
bru run /path/to/collection --env Development
# Spezifische Variable überschreiben
bru run /path/to/collection --env Production --variable apiKey=abc123
Bei Fehler fehlschlagen
# Mit nicht-Null-Status beenden, wenn ein Test fehlschlägt (nützlich für CI/CD)
bru run /path/to/collection --failOnError
Ausführliche Ausgabe
# Detaillierte Anfrage-/Antwortwort-Informationen anzeigen
bru run /path/to/collection --verbose
Umgebungsvariablen
Umgebungsdatei erstellen
Umgebungsdateien werden als environments/EnvName.json gespeichert:
{
"baseUrl": "https://api.example.com",
"apiKey": "your-api-key-here",
"authToken": "bearer-token",
"userId": "12345",
"timeout": 5000
}
Variablen in Anfragen verwenden
get {
url: {{baseUrl}}/api/users/{{userId}}
timeout: {{timeout}}
}
headers {
Authorization: Bearer {{authToken}}
X-API-Key: {{apiKey}}
}
Umgebungen wechseln
# Über CLI
bru run /path/to/collection --env Development
# Über GUI: Umgebungs-Dropdown in Bruno-Schnittstelle auswählen
Umgebungsvariablen-Typen
| Typ | Beispiel | Verwendung |
|---|---|---|
| String | "apiKey": "abc123" | {{apiKey}} |
| Number | "timeout": 5000 | {{timeout}} |
| Boolean | "debug": true | {{debug}} |
| Object | "config": {...} | Zugriff mit Scripting |
Secrets-Management
# .env-Datei für sensible Daten erstellen (zu .gitignore hinzufügen)
echo "PROD_API_KEY=secret123" > .env
# In Umgebungsdatei mit Referenz verwenden
# Oder Bruno-GUI verwenden, um Felder als "Secret" zu markieren
Pre-Request-Skripte
Fügen Sie JavaScript hinzu, bevor die Anfrage gesendet wird:
// Dynamische Werte setzen
bru.setEnvVar('timestamp', Date.now());
bru.setEnvVar('nonce', Math.random().toString(36).substring(7));
// Bedingte Logik
if (bru.getEnvVar('env') === 'production') {
bru.setEnvVar('timeout', 10000);
}
// Debug-Info protokollieren
console.log('Sending request to', bru.getEnvVar('baseUrl'));
Post-Response-Skripte
Führen Sie JavaScript nach Erhalt der Antwort aus:
// Zugriff auf Antwortdaten
const responseData = res.getBody();
const statusCode = res.getStatus();
const headers = res.getHeaders();
// Werte für nächste Anfrage speichern
if (statusCode === 200) {
bru.setEnvVar('authToken', responseData.token);
bru.setEnvVar('userId', responseData.user.id);
}
// Antwort protokollieren
console.log('Status:', statusCode);
console.log('Response:', JSON.stringify(responseData, null, 2));
Häufige Response-Operationen
// Statuscode abrufen
const status = res.getStatus();
// Body als String abrufen
const body = res.getBody();
// JSON-Body parsen
const data = res.getBody(true); // true = als JSON parsen
// Header abrufen
const contentType = res.getHeader('content-type');
// Spezifischen Header abrufen
const authHeader = res.getHeader('authorization');
Assertions und Tests
Integrierte Test-Assertions
// Statuscode-Assertion
tests['Status is 200'] = (res.getStatus() === 200);
// Response-Body enthält
tests['Response contains user'] = res.getBody().includes('john');
// JSON-Response-Validierung
const data = res.getBody(true);
tests['User ID exists'] = data.user && data.user.id > 0;
// Response-Zeit
tests['Response time < 500ms'] = res.getResponseTime() < 500;
// Header-Validierung
tests['Content-Type is JSON'] = res.getHeader('content-type').includes('application/json');
Komplexes Test-Beispiel
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));
// Für nächste Anfrage speichern
if (tests['Status is 201']) {
bru.setEnvVar('newUserId', data.id);
}
Authentifizierung
Bearer Token
auth:bearer {
token: {{authToken}}
}
Basic Auth
auth:basic {
username: {{username}}
password: {{password}}
}
API-Schlüssel (Header)
headers {
X-API-Key: {{apiKey}}
Authorization: ApiKey {{apiKey}}
}
API-Schlüssel (Query-Parameter)
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
}
Digest Auth
auth:digest {
username: {{username}}
password: {{password}}
}
Anfrage-Typen und Methoden
GET-Anfrage
meta {
name: Fetch User
type: http
seq: 1
}
get {
url: {{baseUrl}}/api/users/{{userId}}
}
params:query {
includeProfile: true
fields: id,name,email
}
POST-Anfrage
post {
url: {{baseUrl}}/api/users
}
body:json {
{
"name": "Jane Doe",
"email": "jane@example.com"
}
}
PUT/PATCH-Anfrage
put {
url: {{baseUrl}}/api/users/{{userId}}
}
body:json {
{
"name": "Jane Smith",
"status": "active"
}
}
DELETE-Anfrage
delete {
url: {{baseUrl}}/api/users/{{userId}}
}
Anfrage mit Headers
headers {
Content-Type: application/json
Accept: application/json
User-Agent: Bruno/v1.0
X-Request-ID: {{requestId}}
Authorization: Bearer {{token}}
}
Erweiterte Funktionen
Variablen auf Sammlungsebene
Definieren Sie Variablen in bruno.json:
{
"name": "My API Collection",
"version": "1.0",
"variables": {
"baseUrl": "https://api.example.com",
"version": "v1",
"defaultTimeout": 5000
}
}
Anfrage-Sequenzierung
Kontrollieren Sie die Ausführungsreihenfolge in CLI runner:
meta {
name: Authenticate
type: http
seq: 1
}
meta {
name: Get User Data
type: http
seq: 2
}
Anfragen werden in seq-Reihenfolge ausgeführt.
GraphQL-Abfragen
meta {
name: GraphQL Query
type: http
seq: 1
}
post {
url: {{baseUrl}}/graphql
}
body:graphql {
query {
user(id: "{{userId}}") {
id
name
email
}
}
}
Query-Parameter
params:query {
page: 1
limit: 10
sort: -createdAt
filter: status:active
}
Git-Workflow
Warum Git-Native wichtig ist
# Sammlungen werden als Textdateien gespeichert
.bru/
├── users/
│ ├── get-user.bru
│ └── create-user.bru
└── products/
└── list-products.bru
# Einfache Versionskontrolle
git add .
git commit -m "Update API requests"
git push origin main
# Merge-Konflikte sind handhabbar
# Änderungen in Pull Requests überprüfen
# Mit Team zusammenarbeiten
Zusammenarbeits-Workflow
# Teamkollege klont Sammlung
git clone https://github.com/team/api-collection.git
cd api-collection
# Bruno CLI installieren
npm install -g @usebruno/cli
# Tests lokal ausführen
bru run . --env Development
# Änderungen vornehmen
# Neue Anfragen hinzufügen oder vorhandene aktualisieren
# Commiten und pushen
git add .
git commit -m "Add payment API endpoints"
git push origin feature/payments
Sensible Dateien ignorieren
# .gitignore im Sammlungsstamm
.env
.env.local
environments/Production.json
!environments/Production.json.example
secrets/
node_modules/
CI/CD-Integration
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
Lokaler Pre-commit Hook
#!/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
Häufige Workflows
REST-API testen
# 1. Umgebung einrichten
bru run /path/to/collection --env Development
# 2. Testergebnisse überprüfen
# Tests bestanden/fehlgeschlagen in der Ausgabe angezeigt
# 3. Report generieren
bru run /path/to/collection --env Development --reporter html --output report.html
Load Testing mit parallelen Anfragen
// Im Pre-Request-Skript
for (let i = 0; i < 10; i++) {
bru.setEnvVar('iteration', i);
}
Dynamische Daten generieren
// Eindeutige E-Mail pro Anfrage generieren
const timestamp = Date.now();
bru.setEnvVar('dynamicEmail', `user_${timestamp}@example.com`);
// Zufällige ID generieren
bru.setEnvVar('randomId', Math.floor(Math.random() * 10000));
Anfragen verketten
// Im Post-Response-Skript der ersten Anfrage
const data = res.getBody(true);
bru.setEnvVar('userId', data.id);
// Nächste Anfrage verwendet {{userId}}
Debugging
Ausführlichen Modus aktivieren
bru run /path/to/collection --verbose
Anfrage-/Antwortwort-Details anzeigen
In Bruno GUI:
- Anfrage anklicken
- “Params”-Registerkarte für Query-Parameter anzeigen
- “Body”-Registerkarte für Anfrage-Text anzeigen
- “Response”-Registerkarte für Antwortdaten anzeigen
- “Tests”-Registerkarte für Testergebnisse anzeigen
Console-Protokollierung
// In Pre-Request- oder Post-Response-Skripten
console.log('Variable value:', bru.getEnvVar('baseUrl'));
console.log('Full response:', res.getBody());
console.log('Status code:', res.getStatus());
Netzwerk-Inspektion
// Response-Header überprüfen
const headers = res.getHeaders();
console.log('All headers:', headers);
// Response-Zeit überprüfen
console.log('Response time:', res.getResponseTime(), 'ms');
Best Practices für Dateistruktur
api-collection/
├── README.md # Dokumentation
├── .gitignore # Sensible Dateien ignorieren
├── bruno.json # Sammlungsmetadaten
├── environments/ # Umgebungsdateien
│ ├── Development.json
│ ├── Staging.json
│ └── Production.json
├── globals.json # Globale Variablen
├── 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
Ressourcen
| Ressource | URL |
|---|---|
| Offizielle Website | usebruno.com |
| GitHub Repository | github.com/usebruno/bruno |
| Dokumentation | docs.usebruno.com |
| Download | usebruno.com/downloads |
| Discord Community | discord.gg/usebruno |
| Bru Language Spec | github.com/usebruno/bru |
| API Testing Guide | docs.usebruno.com/api-testing |
| GitHub Issues | github.com/usebruno/bruno/issues |
Tipps und Tricks
- Git Diff für Reviews: Da Sammlungen Dateien sind, verwenden Sie
git diff, um API-Änderungen vor dem Mergen zu überprüfen - Umgebungs-Templates: Erstellen Sie
.example.json-Dateien für Umgebungen, um die Konfigurationsstruktur ohne Secrets zu teilen - Wiederverwendbare Skripte: Speichern Sie häufige Test-Skripte in separaten
.js-Dateien und referenzieren Sie sie - Variablen-Scope: Sammlungsvariablen gelten global; Variablen auf Anfrage-Ebene überschreiben sie
- Leistung: Verwenden Sie
--failOnError-Flag in CI/CD, um Test-Fehler früh zu erkennen - Dokumentation: Fügen Sie Kommentare in
.bru-Dateien mit// Kommentar-Syntaxhinzu - Versionierung: Beziehen Sie die API-Version in die Base-URL-Variable ein, um einfach zwischen Versionen zu wechseln