JetClient vs Bruno

This comparison highlights JetClient’s advantages over Bruno.

IDE Integration vs Standalone App

  • Bruno operates as a standalone application with its own script editor, which has limited functionality compared to a professional IDE.
  • JetClient integrates directly with JetBrains IDEs, providing access to advanced features such as code completion, navigation, documentation, refactoring, and AI assistance through tools like GitHub Copilot and JetBrains AI Assistant.

Markdown Sync File Format vs Custom Bru Format

  • Bruno stores requests in separate files using a custom .bru format. While human-readable, this format lacks syntax highlighting in IDEs and platforms like GitHub, GitLab, and Bitbucket.
  • JetClient stores requests and folders in structured Markdown files with dedicated code blocks: metadata in TOML, variables in JSON5, and scripts in JavaScript. These files provide built-in syntax highlighting in IDEs and on platforms like GitHub, GitLab, and Bitbucket, making it easier to review and merge changes.

Code-First Testing vs Folder-Based Testing

  • Bruno structures test scenarios by organizing requests into folders in a specific order, often requiring request duplication for different scenarios. Implementing complex logic with loops and conditions relies on workarounds like setNextRequest, making tests harder to read and maintain.
  • JetClient takes a more flexible approach. While you can still organize requests in folders, its key feature is the ability to write test scenarios in JavaScript, just like in any other programming language. This allows you to build complex logic using conditions, loops, and reusable functions while leveraging the UI to create and manage requests. Requests can be easily referenced in scripts and executed sequentially or in parallel, making test automation more efficient and maintainable.

Multiple Active Environments vs Single Active Environment

  • Bruno allows only one active environment at a time. In complex testing scenarios, you may need different contexts such as user roles, clients, tenants, regions, device platforms, or API versions, each requiring different sets of variables. In Bruno, this means creating multiple environments that combine these contexts. For example, you might have DEV_USER, DEV_ADMIN, PROD_USER, and PROD_ADMIN environments. This approach leads to duplicated variables and increased maintenance overhead. Adding another context results in a combinatorial explosion.
  • JetClient introduces environment groups, allowing you to select multiple environments simultaneously—one from each group. You can create groups for environments (Dev/Prod), roles (User/Admin), etc., and combine them using a multi-selection dropdown, making it easy to switch between different contexts.

JSON5 Variables vs Table Variables

  • Bruno uses a table view for variables, which is limited to simple values and makes large variable sets difficult to manage. Arrays, objects, and complex strings are hard to work with in small table cells. If you need a JSON object, you must store it as a string and parse it in the script.
  • JetClient uses JSON5 for variables, allowing values to be not only primitives but also objects, arrays, and expressions. JSON5 supports comments, which are useful for describing variables. It also supports unquoted properties and single-quoted values, making it cleaner and more readable.

Functions and Inline Expressions

  • Bruno does not support dynamic variables or functions within variable values. If you need dynamic values, you have to generate them in a script before assigning them to variables.
  • JetClient includes a wide range of built-in functions for random data generation. These functions can be used not only as standalone variables (e.g., {{ $randomUserName }}) but also with arguments and even within expressions, such as {{5 + myIntVar * $randomInt(1, 10)}}. Beyond random data generation, JetClient provides powerful functions such as:
    • $readFile - Reads file content
    • $pickOne, $pickSome - Picks one or multiple values from a provided array
    • $repeat - Creates arrays from a given value
    • $textInput, $comboBoxInput, $dateInput, etc. - User prompts with various input types, grouped into a single dialog when used together
    • $eval - Evaluates custom JavaScript expressions, allowing calls to your own functions defined in the Init Script
    • $exec - Executes shell commands, useful for running external scripts or commands like vault, aws, etc.

Expressions can be used not only where variables are referenced but also in variable values:

{
  $randomUser: {
    id: {{ $uuid }},
    email: {{ $randomEmail }}
  },
  
  users: {{ $repeat($randomUser, 10) }}, // Creates an array of 10 random users
  
  credentials: {
    login: {{ $textInput("Enter login") }},
    password: {{ $passwordInput("Enter password") }}
  }
}

Example Requests

  • Bruno does not support request examples, meaning you must duplicate requests to cover different scenarios, leading to clutter and maintenance overhead.
  • JetClient allows you to create examples for requests. Examples act as child requests, inheriting the method and URL from the parent request while allowing different parameters, headers, and body content. This makes it easy to define multiple test cases for the same request without duplication.

Shared and Local Variable Separation

  • Bruno requires users to store private variables in .env files and manually add them to .gitignore to prevent them from being committed. These variables must then be mapped to environment variables, making management and visibility less convenient.
  • JetClient keeps shared and local variables clearly separated using distinct JSON5 editors in a split-view interface, making them easier to manage and view.

Environment-Specific Folder Variables

  • Bruno only supports common folder variables that are shared across all environments.
  • JetClient supports both common and environment-specific folder variables, allowing you to define environment-dependent values at the folder level.

Auto-Save vs Manual Save

  • Bruno requires users to manually save all changes by clicking “Save,” which can be inconvenient and may lead to data loss if forgotten. It also adds unnecessary mental overhead—either you constantly think about saving changes or keep all tabs open until you’re done, delaying the decision until later.
  • JetClient eliminates this concern by combining auto-save and manual save. Changes are always preserved in the plugin state, so you don’t have to worry about losing work. Saving to sync files can be configured to happen automatically or manually using ‘Save’ and ‘Restore’ actions.