Découvrir Bruno : intégrer des tests API dans votre projet de développement

Bruno est un outil open-source de tests API pensé pour les développeurs, en alternative légère à Postman.

Il se distingue par l’utilisation de fichiers texte (.bru) faciles à versionner dans Git et une intégration naturelle aux workflows de développement et CI/CD.

Cet article montre comment, à travers l’exemple de l’API Swagger Petstore, on peut créer et organiser des requêtes, automatiser des tests (assertions, scripts JS), gérer des environnements (dev, prod…) et lancer ces tests en interface graphique, en CLI ou dans Docker.

APIOpen APICI/CDDevOps

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 :

  1. Lancez l'application Bruno.
  2. Au niveau des trois petits points près du logo, cliquez sur "Create Workspace" et donnez-lui le nom api.
  3. Pour l’emplacement, sélectionnez le dossier test de votre projet (ou créez-le si besoin).
  4. 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 :

  1. Faites un clic droit sur le dossier pets/.
  2. Sélectionnez "New Request".
  3. Donnez-lui le nom findByStatus.
  4. Dans la section "Method", choisissez "GET".
  5. Entrez l’URL https://petstore.swagger.io/v2/pet/findByStatus?status=available.
  6. Sauvegardez.
  7. 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 :

  1. Toujours dans le dossier pets/ , faites un clic droit et sélectionnez "New Request".
  2. Donnez le nom findById.
  3. Choisissez "GET" comme méthode.
  4. Renseignez l’URL https://petstore.swagger.io/v2/pet/1.
  5. 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 :

  1. Dans pets/, faites encore "New Request", nommez-la postPet.
  2. Choisissez "POST" comme méthode.
  3. Renseignez l’URL https://petstore.swagger.io/v2/pet.
  4. Dans la partie "Body", sélectionnez le type "JSON".
  5. 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 :

  1. Faites un clic droit sur votre workspace `api` => "New Environment".
  2. Créez un fichier d’environnement `prod.env`.
  3. 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 :

  1. Allez dans votre requête postPet.
  2. 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 »).
  3. 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 :

  1. Faites un clic droit sur le dossier pets/ => "New Request".
  2. Donnez-lui le nom findPostedById.
  3. Choisissez la méthode "GET".
  4. Dans l’URL, utilisez la variable définie par le script précédent : {{baseUrl}}/pet/{{petPostedId}}
  5. 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.