Skip to content

API Testing with Bruno

20-05-2026 Roy de Kleijn
API testing with Bruno banner

Bruno is an open source API client that takes a different stance from the tools that came before it. Instead of keeping your requests in a cloud workspace or a large JSON blob, Bruno stores every request as a plain text file on disk, using a small markup language called Bru. Your collection is a folder of files, and that folder lives in your Git repository. If you have ever wanted API requests to be reviewed in a pull request like normal code, Bruno was built for you.

How it works

Each request is a .bru file. The file describes the method, the URL, headers, the body and any assertions, all in a readable block format. Here is a request that lists brands and checks the result:

get {
  url: {{BASE_URL}}/brands
  body: none
  auth: none
}
tests {
  test("Status code is 200", function () {
      expect(res.getStatus()).to.equal(200);
  });
  test("Size of array", function () {
      var jsonData = res.getBody();
      expect(jsonData.length).to.gte(2);
  });
}

Environments are also plain files, so a test environment can define BASE_URL once and every request reuses it. Assertions are written in JavaScript with a Chai style expect, which will feel familiar if you have used Postman. You can drive Bruno through its desktop app while you work, then run the whole collection headless with the Bruno CLI using bru run, producing an HTML report for the pipeline.

Benefits

The plain text format is the whole story. Diffs are clean, so a reviewer can see exactly which header or assertion changed. There is no account to create and no sync service in the middle, because the files are simply on your machine. It is fast, it is offline friendly, and it fits naturally into the same review process you already use for source code. For teams that dislike storing test logic in an opaque format, this is a real relief.

Downsides

Bruno is younger than the established clients, so the ecosystem is smaller and some advanced features are still maturing. The Bru language is specific to Bruno, so knowledge does not transfer directly to other tools. As with any client that keeps assertions in small scripts, very large suites still lack the module structure you would get from a full programming language. For straightforward request level checks, though, it is more than enough.

What the example project tests

The repository at github.com/testsmith-io/api-test-automation-bruno targets the Practice Software Testing API at https://api.practicesoftwaretesting.com, the same ToolShop backend used across this series. The BASE_URL is defined in environments/test.bru.

Three scenarios are covered. A GET /brands request checks for status 200 and at least two brands. A POST /users/login request confirms status 200 and the presence of an access_token. An Invoices folder holds a login request that captures the token followed by a protected GET /invoices call that sends the Bearer header and verifies the response. Running bru run --env test executes all of them and writes a report.

A GitHub Actions workflow installs the Bruno CLI, runs the collection on every push and on a weekly cron, and uploads the HTML result. It is the same three checks as the Postman example, which is exactly the point: you can put the two side by side and decide which format you would rather maintain.

Delen:
Roy de Kleijn

Test Automation Expert

Met meer dan 15 jaar ervaring in software testing en test automation helpt Roy teams om hun testprocessen te verbeteren.

Wil je meer leren?

Bekijk onze trainingen en breng je test automation skills naar het volgende niveau.