Introduction / Présentation de Bruno
Dans notre précédent article "Bruno vs Yaak", nous vous présentions Bruno, un outil open-source orienté développeurs qui se positionne comme une alternative légère et rapide à Postman.
Bruno se distingue par sa simplicité, son format de requêtes stockées en fichiers texte (.bru
), et sa parfaite intégration dans les workflows Git.
Dans cet article, nous allons illustrer l’utilisation de Bruno avec l’API publique Petstore proposée par Swagger — une API publique de démonstration idéale pour apprendre à écrire et tester des requêtes.
Créer un projet Bruno
Intégrer Bruno dans votre projet
Pour bien organiser vos tests, nous vous conseillons de créer un sous-répertoire dédié dans votre projet, par exemple test
si celui-ci n'est pas déjà présent. Dans notre exemple, ce répertoire existe et contient également des tests unitaires sous test/unit
.
Comment faire via l'interface :
- Lancez l'application Bruno.
- Au niveau des trois petits points près du logo, cliquez sur "Create Workspace" et donnez-lui le nom
api
. - Pour l’emplacement, sélectionnez le dossier
test
de votre projet (ou créez-le si besoin). - Une fois le workspace créé, faites un clic droit dessus et choisissez "New Folder", puis nommez-le
pets/
pour regrouper les requêtes liées aux animaux.
Votre arborescence ressemblera ensuite à ceci :
your-project └── test └── api └── pets └── unit └── UnitTest1.php
Écrire vos premières requêtes
Obtenir la liste des animaux disponibles
Via l'interface :
- Faites un clic droit sur le dossier
pets/
. - Sélectionnez "New Request".
- Donnez-lui le nom
findByStatus
. - Dans la section "Method", choisissez "GET".
- Entrez l’URL
https://petstore.swagger.io/v2/pet/findByStatus?status=available
. - Sauvegardez.
- Vous pouvez tester la requête en cliquant sur la flèche située à droite de l'URL de la requête.
Vous verrez ensuite qu'un fichier pets/findByStatus.bru
est maintenant présent.
meta { name: findByStatus type: http seq: 1 } get { url: https://petstore.swagger.io/v2/pet/findByStatus?status=available body: none auth: none } query { status: available }
Récupérer un animal par son ID
Via l'interface :
- Toujours dans le dossier
pets/
, faites un clic droit et sélectionnez "New Request". - Donnez le nom
findById
. - Choisissez "GET" comme méthode.
- Renseignez l’URL
https://petstore.swagger.io/v2/pet/1
. - Sauvegardez.
Le fichier pets/findById.bru
a été créé.
meta { name: findById type: http seq: 2 } get { url: https://petstore.swagger.io/v2/pet/{{petId}} body: none auth: none }
Ajouter un nouvel animal
Via l'interface :
- Dans
pets/
, faites encore "New Request", nommez-lapostPet
. - Choisissez "POST" comme méthode.
- Renseignez l’URL
https://petstore.swagger.io/v2/pet
. - Dans la partie "Body", sélectionnez le type "JSON".
- Copiez-collez le JSON suivant dans le body :
{ "id": 999, "name": "Médor", "status": "available", "photoUrls": ["https://upload.wikimedia.org/wikipedia/commons/4/43/Cute_dog.jpg"], "tags": [ { "name": "friendly" } ] }
Puis sauvegardez. Le fichier pets/postPet
a été créé.
meta { name: postPet type: http seq: 3 } post { url: {{baseUrl}}/pet body: json auth: none } body:json { { "id": 999, "name": "Médor", "status": "available", "photoUrls": ["https://upload.wikimedia.org/wikipedia/commons/4/43/Cute_dog.jpg"], "tags": [ { "name": "friendly" } ] } }
À ce stade, vous disposez d'une petite collection de requêtes qui vous permet d'exécuter des tests manuels en lançant des requêtes prédéfinies.
Vous pouvez d'ores et déjà committer vos fichiers Bruno dans votre projet afin de les partager avec votre équipe, tâche basique mais pas si simple à faire avec Postman.
Implémenter des tests automatiques
Bruno permet d’ajouter des assertions simples directement dans vos requêtes. Cela rend vos fichiers .bru
à la fois lisibles et puissants, et vous inscrit dans une logique de tests automatisés semblable à celle d’outils comme Jest ou Mocha.
Par exemple, pour la requête postPet
, après avoir ajouté un nouvel animal, on peut vérifier que le corps de la réponse contient bien le nom "Médor" et que le statut est correct :
assert { res.body.name: eq Médor res.body.status: eq available res.status: eq 200 }
Bruno propose aussi un bloc tests
qui permet d’écrire des tests plus complexes, d’enchaîner des vérifications, et même de faire du logging pour diagnostiquer des erreurs.
tests { test("should have worked with status 200", function () { expect(res.getStatus()).to.equal(200); }); test("pet name should equal Médor", function () { expect(res.getBody().name).to.equal('Médor'); }); test("pet status should equal available", function () { expect(res.getBody().status).to.equal('available'); }); }
Ces deux types de tests peuvent être directement ajoutés aux fichiers de requête en .bru
ou via l'interface dans les onglets Tests
et Assert
d'une requête. Bruno fonctionne de manière bi-directionnelle entre son interface et ses fichiers de configuration.
Exploiter les variables d’environnement
Définir des variables d'environnement va vous permettre d'exécuter vos tests et vos requêtes dans différents contextes, par exemple dans un environnement local de développement, un environnement de recette (QA), voire en environnement de production.
Définir des variables
Comment faire via l'interface :
- Faites un clic droit sur votre workspace `api` => "New Environment".
- Créez un fichier d’environnement `prod.env`.
- Ajoutez la ligne suivante : 'name : baseUrl' et 'value : https://petstore.swagger.io/v2'
Un fichier d'environnement a été créé sous le dossier environnement
et contient les variables ajoutés. Ensuite, dans vos requêtes, vous pourrez remplacer l’URL en dur par {{baseUrl}}
, soit directement dans les fichiers, soit via l'interface :
url: {{baseUrl}}/pet/findByStatus?status=available
Utiliser les scripts avant/après requête
Bruno permet d’exécuter des scripts JavaScript avant l’envoi d’une requête (pre-request) ou juste après avoir reçu la réponse (post-response).
Cela est particulièrement pratique pour :
- transformer une réponse,
- extraire des données pour une requête suivante,
- ou encore initialiser des variables dynamiques.
Nous allons le mettre en place sur un cas concret : vous créez un nouvel animal avec une requête POST, et vous voulez ensuite récupérer cet animal avec une requête GET en utilisant dynamiquement l’ID généré.
Étape 1 : Sauvegarder l’ID renvoyé après la création
Via l’interface :
- Allez dans votre requête
postPet
. - Dans l’éditeur, trouvez la section "Scripts" (elle apparaît sous la requête quand vous scrollez ou en cliquant sur l’icône « code »).
- Dans le champ "Post-response script", ajoutez le code suivant :
let data = res.body; bru.setEnvVar("petPostedId", data.id);
Ce script sera exécuté après que Bruno récupère la réponse du POST : il récupère l’ID du nouvel animal et le stocke dans une variable d’environnement petPostedId
. Vous pouvez ensuite la réutiliser dans d’autres requêtes.
Étape 2 : Créer une requête GET dynamique
Via l’interface :
- Faites un clic droit sur le dossier
pets/
=> "New Request". - Donnez-lui le nom
findPostedById
. - Choisissez la méthode "GET".
- Dans l’URL, utilisez la variable définie par le script précédent :
{{baseUrl}}/pet/{{petPostedId}}
- Sauvegardez.
Limite importante
Dans l’API Petstore, si vous ne forcez pas explicitement un ID dans votre requête POST ("id": 999
), l’API génère parfois un ID aléatoire… Et cet ID n’est pas toujours exploitable ensuite par le endpoint GET, qui peut retourner une erreur (animal non trouvé).
C’est pourquoi même avec le script qui récupère dynamiquement l’ID, vous devez forcer un ID fixe dans la requête POST pour que l’appel GET suivant fonctionne de façon fiable.
Cette limite est spécifique à l'API Petstore utilisée pour l'exemple, vous n'aurez certainement pas cette contrainte dans votre projet.
Fichiers Bruno complets
Le fichier postPet.bru
a ce bloc en plus après avoir ajouté le script :
script:post-response { let data = res.body; bru.setEnvVar("petPostedId", data.id); }
Et le fichier findPostedById.bru
correspond à :
meta { name: findPostedById type: http seq: 4 } get { url: baseUrl/pet/petPostedId body: none auth: none }
Lancer les tests
Bruno permet de lancer les tests via l'interface ou en mode CLI, très pratique pour l’intégration continue.
- Via l'interface : faire un clic droit sur la collection dans la barre de navigation de gauche et cliquer sur "Run".
- Avec Node.js : ajoutez Bruno comme dépendance dans votre
package.json
, puis lancez :npx bru run test/api
- Avec Docker : Bruno propose une image officielle pour exécuter vos tests dans un container, à la racine de votre projet, lancez :
docker run -ti --rm -v "$(pwd)/
/test/api":/apps -w /apps alpine/bruno run --env=prod
Cela montera votre projet local dans le container et exécutera les tests présents dans test/api
.
Vous pouvez aussi compléter votre workflow avec un Makefile ou automatiser cela via un pipeline CI/CD (par ex. GitHub Actions, GitLab CI, etc).
Conclusion
Bruno s’impose comme un outil efficace et moderne pour tester vos APIs, tout en s’intégrant naturellement dans le quotidien des développeurs. Sa légèreté, sa rapidité et surtout son format textuel en fichiers .bru
en font un excellent choix pour versionner vos tests et les partager facilement au sein d’une équipe.
Grâce à la prise en charge des variables d’environnement, des scripts avant et après requête, ainsi que des tests en JavaScript, Bruno permet de construire des scénarios de test complets et dynamiques. Vous pouvez ainsi automatiser vos vérifications et les intégrer simplement dans votre pipeline d’intégration continue.
Enfin, la possibilité d’importer des collections Postman (avec quelques ajustements nécessaires) facilite la migration ou la reprise de projets existants.
Pour illustrer concrètement ces usages, l’exemple complet présenté dans cet article est disponible sur notre dépôt GitHub. N’hésitez pas à l’explorer pour démarrer rapidement ou adapter ces pratiques à vos propres projets.