bruno-api-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBruno API Testing
Bruno API测试
Create and run API test collections using Bruno — a Git-first, offline-only API client that stores collections as plain files.
使用Bruno创建并运行API测试集合——Bruno是一款优先支持Git、仅离线使用的API客户端,以纯文件形式存储集合。
Format Selection
格式选择
Bruno supports two file formats. Determine which to use:
- YAML (OpenCollection) — Default since Bruno v3.1. Uses files and
.ymlroot. Preferred for new projects.opencollection.yml - Bru (Legacy) — Uses files and
.bruroot. Use only for existing Bru-format collections.bruno.json
Detect format by checking the collection root: → YAML, → Bru.
opencollection.ymlbruno.jsonFor YAML format syntax details, see references/yaml-syntax.md.
For Bru format syntax details, see references/bru-syntax.md.
Bruno支持两种文件格式。请确定要使用的格式:
- YAML(OpenCollection) —— Bruno v3.1起的默认格式。使用.yml文件和opencollection.yml根文件。推荐用于新项目。
- Bru(旧版) —— 使用.bru文件和bruno.json根文件。仅用于现有Bru格式的集合。
通过检查集合根文件判断格式:存在opencollection.yml则为YAML格式,存在bruno.json则为Bru格式。
关于YAML格式的语法细节,请查看references/yaml-syntax.md。
关于Bru格式的语法细节,请查看references/bru-syntax.md。
Workflow
工作流程
1. Create Collection Structure
1. 创建集合结构
Create the directory layout with the collection root file, environments, and organized request folders.
YAML format:
my-api-tests/
├── opencollection.yml # REQUIRED: collection root
├── environments/
│ ├── Local.yml
│ ├── Staging.yml
│ └── Production.yml
├── Auth/
│ ├── folder.yml
│ └── Login.yml
└── Users/
├── folder.yml
├── Get Users.yml
├── Get User by ID.yml
└── Create User.ymlMinimal :
opencollection.ymlyaml
opencollection: 1.0.0
info:
name: My API TestsBru format: Same structure but use + extensions. See references/bru-syntax.md.
bruno.json.bru创建包含集合根文件、环境配置和有序请求文件夹的目录布局。
YAML格式:
my-api-tests/
├── opencollection.yml # 必填:集合根文件
├── environments/
│ ├── Local.yml
│ ├── Staging.yml
│ └── Production.yml
├── Auth/
│ ├── folder.yml
│ └── Login.yml
└── Users/
├── folder.yml
├── Get Users.yml
├── Get User by ID.yml
└── Create User.yml极简版opencollection.yml:
yaml
opencollection: 1.0.0
info:
name: My API TestsBru格式: 结构相同,但使用bruno.json + .bru扩展名。请查看references/bru-syntax.md。
2. Create Environment Files
2. 创建环境文件
YAML ():
environments/Local.ymlyaml
variables:
- name: baseUrl
value: http://localhost:3000/api
- name: apiKey
value: ""
secret: trueBru ():
environments/Local.bruvars {
baseUrl: http://localhost:3000/api
}
vars:secret [
apiKey
]YAML格式(environments/Local.yml):
yaml
variables:
- name: baseUrl
value: http://localhost:3000/api
- name: apiKey
value: ""
secret: trueBru格式(environments/Local.bru):
vars {
baseUrl: http://localhost:3000/api
}
vars:secret [
apiKey
]3. Write Request Files with Tests
3. 编写带测试的请求文件
YAML format — a complete request with tests:
yaml
info:
name: Get Users
type: http
seq: 1
http:
method: GET
url: "{{baseUrl}}/users"
headers:
- name: accept
value: application/json
- name: authorization
value: "Bearer {{authToken}}"
runtime:
assertions:
- expression: res.status
operator: eq
value: "200"
- expression: res.body
operator: isArray
scripts:
- type: tests
code: |-
test("returns 200", function() {
expect(res.status).to.equal(200);
});
test("returns array of users", function() {
expect(res.body).to.be.an('array');
expect(res.body).to.have.lengthOf.at.least(1);
});
test("each user has required fields", function() {
res.body.forEach(user => {
expect(user).to.have.property('id');
expect(user).to.have.property('email');
});
});
settings:
encodeUrl: trueUse assertions (declarative) for simple checks, tests scripts (Chai.js) for complex logic.
YAML格式——包含测试的完整请求:
yaml
info:
name: Get Users
type: http
seq: 1
http:
method: GET
url: "{{baseUrl}}/users"
headers:
- name: accept
value: application/json
- name: authorization
value: "Bearer {{authToken}}"
runtime:
assertions:
- expression: res.status
operator: eq
value: "200"
- expression: res.body
operator: isArray
scripts:
- type: tests
code: |-
test("returns 200", function() {
expect(res.status).to.equal(200);
});
test("returns array of users", function() {
expect(res.body).to.be.an('array');
expect(res.body).to.have.lengthOf.at.least(1);
});
test("each user has required fields", function() {
res.body.forEach(user => {
expect(user).to.have.property('id');
expect(user).to.have.property('email');
});
});
settings:
encodeUrl: true简单检查使用断言(声明式),复杂逻辑使用测试脚本(Chai.js)。
4. Chain Requests with Data Extraction
4. 数据提取实现请求链式调用
Extract data from one response and use it in subsequent requests:
YAML — Login request saving a token:
yaml
info:
name: Login
type: http
seq: 1
http:
method: POST
url: "{{baseUrl}}/auth/login"
body:
type: json
data: |-
{
"username": "{{username}}",
"password": "{{password}}"
}
auth:
type: none
runtime:
scripts:
- type: after-response
code: |-
bru.setEnvVar("authToken", res.body.access_token);
- type: tests
code: |-
test("login successful", function() {
expect(res.status).to.equal(200);
expect(res.body).to.have.property('access_token');
});Then reference in subsequent requests via .
{{authToken}}Bearer {{authToken}}从一个响应中提取数据并在后续请求中使用:
YAML格式——保存令牌的登录请求:
yaml
info:
name: Login
type: http
seq: 1
http:
method: POST
url: "{{baseUrl}}/auth/login"
body:
type: json
data: |-
{
"username": "{{username}}",
"password": "{{password}}"
}
auth:
type: none
runtime:
scripts:
- type: after-response
code: |-
bru.setEnvVar("authToken", res.body.access_token);
- type: tests
code: |-
test("login successful", function() {
expect(res.status).to.equal(200);
expect(res.body).to.have.property('access_token');
});随后在后续请求中通过引用。
Bearer {{authToken}}{{authToken}}5. Run Tests with bru CLI
5. 使用bru CLI运行测试
Install and run:
bash
npm install -g @usebruno/cli安装并运行:
bash
npm install -g @usebruno/cliRun entire collection
运行整个集合
cd my-api-tests && bru run --env Local
cd my-api-tests && bru run --env Local
Run specific folder
运行特定文件夹
bru run Auth --env Local
bru run Auth --env Local
Run with developer mode (for external packages, fs access)
开发者模式运行(支持外部包、文件系统访问)
bru run --env Local --sandbox=developer
bru run --env Local --sandbox=developer
Filter by tags
按标签筛选运行
bru run --tags=smoke --env Local
bru run --tags=smoke --env Local
Generate reports
生成报告
bru run --env Local
--reporter-html results.html
--reporter-junit results.xml
--reporter-json results.json
--reporter-html results.html
--reporter-junit results.xml
--reporter-json results.json
bru run --env Local
--reporter-html results.html
--reporter-junit results.xml
--reporter-json results.json
--reporter-html results.html
--reporter-junit results.xml
--reporter-json results.json
Pass secrets via CLI
通过CLI传递密钥
bru run --env Local --env-var API_KEY=secret123
bru run --env Local --env-var API_KEY=secret123
Parallel execution
并行执行
bru run --env Local --parallel
bru run --env Local --parallel
Data-driven testing
数据驱动测试
bru run --csv-file-path data.csv --env Local
**v3.0.0 breaking change**: Default is now Safe Mode. Use `--sandbox=developer` for developer mode features.bru run --csv-file-path data.csv --env Local
**v3.0.0破坏性变更**:默认模式现在是安全模式。如需开发者模式功能,请使用`--sandbox=developer`。6. Set Up CI/CD
6. 搭建CI/CD
See references/ci-cd.md for complete GitHub Actions workflows, matrix testing, and reporting patterns.
Minimal GitHub Actions workflow:
yaml
name: API Tests
on: [push, pull_request]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm install -g @usebruno/cli
- name: Run API Tests
working-directory: ./my-api-tests
env:
API_KEY: ${{ secrets.API_KEY }}
run: bru run --env CI --reporter-html results.html --reporter-junit results.xml
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: |
./my-api-tests/results.html
./my-api-tests/results.xmlCritical: Always set to the collection root in CI/CD.
working-directory完整的GitHub Actions工作流、矩阵测试和报告模式,请查看references/ci-cd.md。
极简版GitHub Actions工作流:
yaml
name: API Tests
on: [push, pull_request]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm install -g @usebruno/cli
- name: Run API Tests
working-directory: ./my-api-tests
env:
API_KEY: ${{ secrets.API_KEY }}
run: bru run --env CI --reporter-html results.html --reporter-junit results.xml
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: |
./my-api-tests/results.html
./my-api-tests/results.xml关键注意事项:在CI/CD中务必将设置为集合根目录。
working-directoryTesting Patterns
测试模式
Assertions (Declarative) — Use for Simple Checks
断言(声明式)——用于简单检查
yaml
runtime:
assertions:
- expression: res.status
operator: eq
value: "200"
- expression: res.body.success
operator: eq
value: "true"
- expression: res.body.data
operator: isJson
- expression: res.headers.content-type
operator: contains
value: application/jsonOperators vary slightly by Bruno version and editor surface. Check Bruno's current Assertions docs for the exact operator names supported by your version when writing declarative assertions.
yaml
runtime:
assertions:
- expression: res.status
operator: eq
value: "200"
- expression: res.body.success
operator: eq
value: "true"
- expression: res.body.data
operator: isJson
- expression: res.headers.content-type
operator: contains
value: application/json操作符会因Bruno版本和编辑器界面略有不同。编写声明式断言时,请查看Bruno当前的断言文档,确认您使用的版本支持的准确操作符名称。
Tests (Chai.js) — Use for Complex Validation
测试(Chai.js)——用于复杂验证
yaml
runtime:
scripts:
- type: tests
code: |-
test("status and structure", function() {
expect(res.status).to.equal(200);
expect(res.body).to.be.an('object');
expect(res.body).to.have.all.keys('id', 'name', 'email');
});
test("validates email format", function() {
expect(res.body.email).to.match(/^[\w\-.]+@([\w-]+\.)+[\w-]{2,4}$/);
});
test("response time acceptable", function() {
expect(res.responseTime).to.be.below(2000);
});
test("pagination works", function() {
expect(res.body.data).to.be.an('array');
expect(res.body.meta.total).to.be.a('number');
expect(res.body.meta.page).to.equal(1);
});For the complete JavaScript API (, , objects), see references/javascript-api.md.
reqresbruyaml
runtime:
scripts:
- type: tests
code: |-
test("status and structure", function() {
expect(res.status).to.equal(200);
expect(res.body).to.be.an('object');
expect(res.body).to.have.all.keys('id', 'name', 'email');
});
test("validates email format", function() {
expect(res.body.email).to.match(/^[\w\-.]+@([\w-]+\.)+[\w-]{2,4}$/);
});
test("response time acceptable", function() {
expect(res.responseTime).to.be.below(2000);
});
test("pagination works", function() {
expect(res.body.data).to.be.an('array');
expect(res.body.meta.total).to.be.a('number');
expect(res.body.meta.page).to.equal(1);
});完整的JavaScript API(、、对象)请查看references/javascript-api.md。
reqresbruCommon Mistakes
常见错误
- Missing (YAML) or
opencollection.yml(Bru) at collection rootbruno.json - Using instead of
meta:in YAML request filesinfo: - Using script type instead of
test(plural)tests - Putting request-level fields (,
http:) inmethod:opencollection.yml - Forgetting in CI/CD steps
working-directory - Committing secrets — use in env files + CI/CD secrets
secret: true - Using for body data is required in YAML to preserve JSON formatting
|- - Missing number in
seq— controls execution orderinfo: - Relying on script/auth inheritance in CLI — Bruno's Sandwich execution order (Collection → Folder → Request) for
folder.ymlscripts may work in the Bruno GUI, butbefore-requestdoes NOT reliably inherit@usebruno/cliscripts or auth settings to individual test files. Always addfolder.ymlscripts andbefore-requestblocks directly to each request file that needs them. Theauthis useful for documentation and GUI users, but CLI-driven tests must be self-contained.folder.yml
- 集合根目录缺少opencollection.yml(YAML格式)或bruno.json(Bru格式)
- 在YAML请求文件中使用而非
meta:info: - 脚本类型使用而非
test(复数形式)tests - 将请求级字段(、
http:)放在opencollection.yml中method: - CI/CD步骤中忘记设置
working-directory - 提交密钥——在环境文件中使用并结合CI/CD密钥管理
secret: true - YAML格式中需要使用来保留JSON格式的请求体数据
|- - 中缺少
info:编号——该编号控制执行顺序seq - 依赖CLI中的folder.yml脚本/认证继承——Bruno的三明治执行顺序(集合→文件夹→请求)适用于脚本在Bruno GUI中的运行,但
before-request并不可靠地将@usebruno/cli脚本或认证设置继承到单个测试文件。务必将folder.yml脚本和before-request块直接添加到每个需要它们的请求文件中。auth对文档和GUI用户有用,但CLI驱动的测试必须是自包含的。folder.yml
Script Execution Order
脚本执行顺序
Bruno supports two script flows:
- Sandwich (default): Collection → Folder
before-request→ Requestbefore-request→ Request is sent → Requestbefore-request→ Folderafter-response→ Collectionafter-responseafter-response - Sequential: Collection → Folder
before-request→ Requestbefore-request→ Request is sent → Collectionbefore-request→ Folderafter-response→ Requestafter-responseafter-response
Request assertions and request run after the post-response scripts.
testsBruno支持两种脚本流程:
- 三明治模式(默认):集合→ 文件夹
before-request→ 请求before-request→ 发送请求 → 请求before-request→ 文件夹after-response→ 集合after-responseafter-response - 顺序模式:集合→ 文件夹
before-request→ 请求before-request→ 发送请求 → 集合before-request→ 文件夹after-response→ 请求after-responseafter-response
请求断言和请求在响应后脚本执行完毕后运行。
tests⚠️ CLI Inheritance Caveat
⚠️ CLI继承警告
The Sandwich/Sequential script execution order described above applies to Bruno GUI only. When running tests with (the CLI runner used in CI/CD), folder-level scripts and settings are NOT reliably inherited by individual request files.
@usebruno/clibefore-requestauthImpact: If a contains a script (e.g., to skip requests when an environment variable is ), request files in that folder will NOT inherit this logic when run via CLI.
folder.ymlbefore-request"false"Workaround: Duplicate the logic into each individual request file that needs it:
before-requestyaml
undefined上述三明治/顺序脚本执行顺序仅适用于Bruno GUI。 使用(CI/CD中使用的CLI运行器)运行测试时,文件夹级别的脚本和设置无法可靠地继承到单个请求文件。
@usebruno/clibefore-requestauth影响:如果包含脚本(例如,当环境变量为时跳过请求),该文件夹中的请求文件在通过CLI运行时将不会继承此逻辑。
folder.ymlbefore-request"false"解决方法:将逻辑复制到每个需要它的请求文件中:
before-requestyaml
undefinedIn each request file that needs conditional skip:
在每个需要条件跳过的请求文件中:
runtime:
scripts:
- type: before-request
code: |-
const featureAvailable = bru.getEnvVar("featureAvailable");
if (featureAvailable === "false") {
bru.runner.skipRequest();
}
- type: tests
code: |-
test("returns 200", function() {
expect(res.status).to.equal(200);
});
**Same applies to auth**: Set `http.auth` in each request file, not just `folder.yml`.runtime:
scripts:
- type: before-request
code: |-
const featureAvailable = bru.getEnvVar("featureAvailable");
if (featureAvailable === "false") {
bru.runner.skipRequest();
}
- type: tests
code: |-
test("returns 200", function() {
expect(res.status).to.equal(200);
});
**认证同理**:在每个请求文件中设置`http.auth`,而不仅仅是在`folder.yml`中。Variable Precedence (Highest to Lowest)
变量优先级(从高到低)
- Runtime variables ()
bru.setVar() - Request variables
- Folder variables
- Collection variables
- Environment variables
Use for global environment values and for OS process environment variables. They are not documented as part of the standard collection variable precedence chain.
bru.getGlobalEnvVar()bru.getProcessEnv()- 运行时变量()
bru.setVar() - 请求变量
- 文件夹变量
- 集合变量
- 环境变量
使用获取全局环境值,使用获取操作系统进程环境变量。它们不属于标准集合变量优先级链的文档范畴。
bru.getGlobalEnvVar()bru.getProcessEnv()References
参考资料
- YAML Syntax — Complete OpenCollection YAML format for requests, bodies, auth, headers, params, environments, folders, collections
- Bru Syntax — Legacy file format reference
.bru - JavaScript API — Full ,
req,resobject API with runner control, cookies, utilitiesbru - CI/CD Integration — GitHub Actions workflows, report generation, matrix testing, environment secrets
- YAML语法 —— 请求、请求体、认证、请求头、参数、环境、文件夹、集合的完整OpenCollection YAML格式说明
- Bru语法 —— 旧版.bru文件格式参考
- JavaScript API —— 完整的、
req、res对象API,包含运行器控制、Cookie、工具函数bru - CI/CD集成 —— GitHub Actions工作流、报告生成、矩阵测试、环境密钥管理