api-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<objective>
Expert-level skill for tool-based API testing using Postman and Bruno. Covers collection organization, environment management, test scripting, response validation, and CI/CD integration.
This skill complements testing-skill (code-based tests) and api-design-skill (API structure). Use this when you need to test existing APIs with dedicated tools rather than writing programmatic tests.
Key distinction:
- testing-skill: Code-based tests (supertest, MSW, pytest requests)
- api-testing-skill: Tool-based tests (Postman, Bruno collections)
- api-design-skill: How to design APIs (structure, conventions) </objective>
<quick_start>
Postman Quick Test:
javascript
// Tests tab in Postman
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Response has user data", function () {
const json = pm.response.json();
pm.expect(json).to.have.property("id");
pm.expect(json).to.have.property("email");
});Bruno Quick Test:
javascript
// tests/get-user.bru
meta {
name: Get User
type: http
seq: 1
}
get {
url: {{baseUrl}}/api/users/{{userId}}
}
tests {
test("should return 200", function() {
expect(res.status).to.equal(200);
});
}Environment Setup:
json
{
"baseUrl": "https://api.example.com",
"apiKey": "test_key_xxx"
}</quick_start>
<success_criteria>
API testing is successful when:
- All endpoints have at least one happy path test
- Error cases tested (4xx, 5xx responses)
- Response schema validated (not just status codes)
- Environment variables used for all configurable values
- Collections organized by resource/domain
- Authentication flows tested end-to-end
- CI pipeline runs collections on every PR
- Test data is reproducible (fixtures or dynamic generation) </success_criteria>
<tool_comparison>
<objective>
基于Postman和Bruno的专家级工具式API测试技能。涵盖集合组织、环境管理、测试脚本编写、响应验证以及CI/CD集成。
本技能与testing-skill(基于代码的测试)和api-design-skill(API结构设计)互为补充。当你需要使用专用工具测试现有API,而非编写程序化测试时,可使用本技能。
核心区别:
- testing-skill:基于代码的测试(supertest、MSW、pytest requests)
- api-testing-skill:基于工具的测试(Postman、Bruno集合)
- api-design-skill:API设计方法(结构、规范) </objective>
<quick_start>
Postman快速测试:
javascript
// Tests tab in Postman
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Response has user data", function () {
const json = pm.response.json();
pm.expect(json).to.have.property("id");
pm.expect(json).to.have.property("email");
});Bruno快速测试:
javascript
// tests/get-user.bru
meta {
name: Get User
type: http
seq: 1
}
get {
url: {{baseUrl}}/api/users/{{userId}}
}
tests {
test("should return 200", function() {
expect(res.status).to.equal(200);
});
}环境配置:
json
{
"baseUrl": "https://api.example.com",
"apiKey": "test_key_xxx"
}</quick_start>
<success_criteria>
API测试成功的标准:
- 所有端点至少包含一个正常流程测试
- 已测试错误场景(4xx、5xx响应)
- 已验证响应 schema(不只是状态码)
- 所有可配置值均使用环境变量
- 集合按资源/领域进行组织
- 已端到端测试认证流程
- CI流水线在每个PR上运行集合测试
- 测试数据可复现(使用固定数据或动态生成) </success_criteria>
<tool_comparison>
Postman vs Bruno
Postman与Bruno对比
| Feature | Postman | Bruno |
|---|---|---|
| Storage | Cloud/Local | Git-native (.bru files) |
| Collaboration | Team sync | Git branches |
| Pricing | Free tier + paid | Free and open source |
| Offline | Desktop app | Full offline |
| Scripting | JavaScript | JavaScript |
| CI/CD | Newman CLI | Bruno CLI |
| Schema | JSON | Plain text .bru |
| Best For | Teams, API documentation | Git workflows, privacy |
| 特性 | Postman | Bruno |
|---|---|---|
| 存储方式 | 云端/本地 | Git原生(.bru文件) |
| 协作方式 | 团队实时同步 | Git分支协作 |
| 定价 | 免费版+付费版 | 免费开源 |
| 离线支持 | 桌面应用支持 | 完全离线可用 |
| 脚本支持 | JavaScript | JavaScript |
| CI/CD集成 | Newman CLI | Bruno CLI |
| Schema格式 | JSON | 纯文本.bru |
| 最佳适用场景 | 团队协作、API文档生成 | Git工作流、隐私需求 |
When to Use Each
适用场景选择
Choose Postman when:
- Team needs real-time collaboration
- API documentation is primary output
- Mock servers needed for frontend dev
- Complex OAuth flows with token refresh
Choose Bruno when:
- Git-native workflow preferred
- Privacy/self-hosting required
- Simpler test scenarios
- Developers prefer code-like syntax </tool_comparison>
<collection_organization>
优先选Postman的场景:
- 团队需要实时协作
- 以API文档生成为主要输出
- 前端开发需要Mock服务器
- 复杂OAuth流程(含令牌刷新)
优先选Bruno的场景:
- 偏好Git原生工作流
- 需隐私保护/自托管
- 测试场景较简单
- 开发者偏好类代码语法 </tool_comparison>
<collection_organization>
Collection Structure
集合结构
Folder Hierarchy
文件夹层级
my-api-tests/
├── auth/
│ ├── login.bru
│ ├── refresh-token.bru
│ └── logout.bru
├── users/
│ ├── create-user.bru
│ ├── get-user.bru
│ ├── update-user.bru
│ └── delete-user.bru
├── orders/
│ ├── create-order.bru
│ ├── get-orders.bru
│ └── cancel-order.bru
├── environments/
│ ├── local.bru
│ ├── staging.bru
│ └── production.bru
└── collection.brumy-api-tests/
├── auth/
│ ├── login.bru
│ ├── refresh-token.bru
│ └── logout.bru
├── users/
│ ├── create-user.bru
│ ├── get-user.bru
│ ├── update-user.bru
│ └── delete-user.bru
├── orders/
│ ├── create-order.bru
│ ├── get-orders.bru
│ └── cancel-order.bru
├── environments/
│ ├── local.bru
│ ├── staging.bru
│ └── production.bru
└── collection.bruNaming Conventions
命名规范
| Element | Convention | Example |
|---|---|---|
| Folders | kebab-case, plural | |
| Requests | verb-noun | |
| Variables | camelCase | |
| Environments | lowercase | |
| 元素 | 规范 | 示例 |
|---|---|---|
| 文件夹 | 短横线命名、复数形式 | |
| 请求 | 动词-名词结构 | |
| 变量 | 小驼峰命名 | |
| 环境 | 全小写 | |
Request Ordering
请求排序
Use sequence numbers for dependent requests:
1. auth/login.bru (seq: 1)
2. users/create-user.bru (seq: 2) - needs auth token
3. users/get-user.bru (seq: 3) - uses created user ID</collection_organization>
<test_patterns>
对依赖请求使用序号标记:
1. auth/login.bru (seq: 1)
2. users/create-user.bru (seq: 2) - 需要认证令牌
3. users/get-user.bru (seq: 3) - 使用创建的用户ID</collection_organization>
<test_patterns>
Test Assertion Patterns
测试断言模式
Status Code Validation
状态码验证
javascript
// Postman
pm.test("Success response", () => pm.response.to.have.status(200));
pm.test("Created response", () => pm.response.to.have.status(201));
pm.test("Not found", () => pm.response.to.have.status(404));
// Bruno
test("Success response", () => expect(res.status).to.equal(200));javascript
// Postman
pm.test("成功响应", () => pm.response.to.have.status(200));
pm.test("创建成功响应", () => pm.response.to.have.status(201));
pm.test("资源不存在", () => pm.response.to.have.status(404));
// Bruno
test("成功响应", () => expect(res.status).to.equal(200));Response Body Validation
响应体验证
javascript
// Postman
pm.test("Has required fields", function () {
const json = pm.response.json();
pm.expect(json).to.have.property("id");
pm.expect(json.id).to.be.a("string");
pm.expect(json.email).to.match(/^[\w-]+@[\w-]+\.\w+$/);
});
// Array validation
pm.test("Returns array of users", function () {
const json = pm.response.json();
pm.expect(json.users).to.be.an("array");
pm.expect(json.users.length).to.be.greaterThan(0);
});javascript
// Postman
pm.test("包含必填字段", function () {
const json = pm.response.json();
pm.expect(json).to.have.property("id");
pm.expect(json.id).to.be.a("string");
pm.expect(json.email).to.match(/^[\w-]+@[\w-]+\.\w+$/);
});
// 数组验证
pm.test("返回用户数组", function () {
const json = pm.response.json();
pm.expect(json.users).to.be.an("array");
pm.expect(json.users.length).to.be.greaterThan(0);
});Response Time Validation
响应时间验证
javascript
pm.test("Response time < 500ms", function () {
pm.expect(pm.response.responseTime).to.be.below(500);
});javascript
pm.test("响应时间<500ms", function () {
pm.expect(pm.response.responseTime).to.be.below(500);
});Header Validation
响应头验证
javascript
pm.test("Content-Type is JSON", function () {
pm.response.to.have.header("Content-Type", /application\/json/);
});
pm.test("Has request ID", function () {
pm.response.to.have.header("X-Request-Id");
});javascript
pm.test("Content-Type为JSON", function () {
pm.response.to.have.header("Content-Type", /application\/json/);
});
pm.test("包含请求ID", function () {
pm.response.to.have.header("X-Request-Id");
});JSON Schema Validation (Postman)
JSON Schema验证(Postman)
javascript
const schema = {
type: "object",
required: ["id", "name", "email"],
properties: {
id: { type: "string", format: "uuid" },
name: { type: "string", minLength: 1 },
email: { type: "string", format: "email" }
}
};
pm.test("Schema is valid", function () {
pm.response.to.have.jsonSchema(schema);
});</test_patterns>
<environment_management>
javascript
const schema = {
type: "object",
required: ["id", "name", "email"],
properties: {
id: { type: "string", format: "uuid" },
name: { type: "string", minLength: 1 },
email: { type: "string", format: "email" }
}
};
pm.test("Schema验证通过", function () {
pm.response.to.have.jsonSchema(schema);
});</test_patterns>
<environment_management>
Environment Management
环境管理
Variable Scopes (Postman)
变量作用域(Postman)
Global → Collection → Environment → Data → Local
(lowest priority) (highest priority)全局 → 集合 → 环境 → 数据 → 本地
(优先级最低) (优先级最高)Environment Files
环境文件
Postman environment.json:
json
{
"id": "env-uuid",
"name": "staging",
"values": [
{ "key": "baseUrl", "value": "https://staging.api.com", "enabled": true },
{ "key": "apiKey", "value": "stg_key_xxx", "enabled": true, "type": "secret" }
]
}Bruno environment:
javascript
// environments/staging.bru
vars {
baseUrl: https://staging.api.com
apiKey: stg_key_xxx
}Postman environment.json:
json
{
"id": "env-uuid",
"name": "staging",
"values": [
{ "key": "baseUrl", "value": "https://staging.api.com", "enabled": true },
{ "key": "apiKey", "value": "stg_key_xxx", "enabled": true, "type": "secret" }
]
}Bruno环境文件:
javascript
// environments/staging.bru
vars {
baseUrl: https://staging.api.com
apiKey: stg_key_xxx
}Dynamic Variables
动态变量
javascript
// Pre-request script - set dynamic values
const timestamp = Date.now();
const uniqueEmail = `test_${timestamp}@example.com`;
// Postman
pm.environment.set("uniqueEmail", uniqueEmail);
pm.environment.set("timestamp", timestamp);
// Bruno (in pre-request)
bru.setVar("uniqueEmail", uniqueEmail);javascript
// 前置请求脚本 - 设置动态值
const timestamp = Date.now();
const uniqueEmail = `test_${timestamp}@example.com`;
// Postman
pm.environment.set("uniqueEmail", uniqueEmail);
pm.environment.set("timestamp", timestamp);
// Bruno(前置请求中)
bru.setVar("uniqueEmail", uniqueEmail);Chaining Requests
请求链式调用
javascript
// Request 1: Login - save token
pm.test("Save auth token", function () {
const json = pm.response.json();
pm.environment.set("authToken", json.accessToken);
pm.environment.set("userId", json.user.id);
});
// Request 2: Use saved token
// Headers: Authorization: Bearer {{authToken}}
// URL: {{baseUrl}}/users/{{userId}}</environment_management>
<authentication_testing>
javascript
// 请求1:登录 - 保存令牌
pm.test("保存认证令牌", function () {
const json = pm.response.json();
pm.environment.set("authToken", json.accessToken);
pm.environment.set("userId", json.user.id);
});
// 请求2:使用保存的令牌
// 请求头:Authorization: Bearer {{authToken}}
// URL: {{baseUrl}}/users/{{userId}}</environment_management>
<authentication_testing>
Authentication Testing
认证测试
Bearer Token Flow
Bearer令牌流程
javascript
// 1. Login request - Pre-request or separate request
// 2. Save token to environment
pm.environment.set("accessToken", pm.response.json().accessToken);
// 3. Use in subsequent requests
// Header: Authorization: Bearer {{accessToken}}javascript
// 1. 登录请求 - 前置请求或独立请求
// 2. 将令牌保存到环境变量
pm.environment.set("accessToken", pm.response.json().accessToken);
// 3. 在后续请求中使用
// 请求头:Authorization: Bearer {{accessToken}}API Key Authentication
API密钥认证
javascript
// Header-based
// X-API-Key: {{apiKey}}
// Query param
// GET {{baseUrl}}/endpoint?api_key={{apiKey}}javascript
// 基于请求头
// X-API-Key: {{apiKey}}
// 基于查询参数
// GET {{baseUrl}}/endpoint?api_key={{apiKey}}OAuth 2.0 with Refresh
带刷新的OAuth 2.0
javascript
// Pre-request script for token refresh
const tokenExpiry = pm.environment.get("tokenExpiry");
const now = Date.now();
if (!tokenExpiry || now > tokenExpiry) {
pm.sendRequest({
url: pm.environment.get("authUrl") + "/token",
method: "POST",
header: { "Content-Type": "application/x-www-form-urlencoded" },
body: {
mode: "urlencoded",
urlencoded: [
{ key: "grant_type", value: "refresh_token" },
{ key: "refresh_token", value: pm.environment.get("refreshToken") },
{ key: "client_id", value: pm.environment.get("clientId") }
]
}
}, (err, res) => {
if (!err) {
const json = res.json();
pm.environment.set("accessToken", json.access_token);
pm.environment.set("tokenExpiry", now + (json.expires_in * 1000));
}
});
}javascript
// 用于令牌刷新的前置请求脚本
const tokenExpiry = pm.environment.get("tokenExpiry");
const now = Date.now();
if (!tokenExpiry || now > tokenExpiry) {
pm.sendRequest({
url: pm.environment.get("authUrl") + "/token",
method: "POST",
header: { "Content-Type": "application/x-www-form-urlencoded" },
body: {
mode: "urlencoded",
urlencoded: [
{ key: "grant_type", value: "refresh_token" },
{ key: "refresh_token", value: pm.environment.get("refreshToken") },
{ key: "client_id", value: pm.environment.get("clientId") }
]
}
}, (err, res) => {
if (!err) {
const json = res.json();
pm.environment.set("accessToken", json.access_token);
pm.environment.set("tokenExpiry", now + (json.expires_in * 1000));
}
});
}Testing Auth Failures
认证失败测试
javascript
// Test unauthorized access
pm.test("Returns 401 without token", function () {
pm.response.to.have.status(401);
});
// Test forbidden access
pm.test("Returns 403 for wrong role", function () {
pm.response.to.have.status(403);
pm.expect(pm.response.json().error).to.include("permission");
});</authentication_testing>
<error_testing>
javascript
// 测试未授权访问
pm.test("无令牌返回401", function () {
pm.response.to.have.status(401);
});
// 测试禁止访问
pm.test("角色错误返回403", function () {
pm.response.to.have.status(403);
pm.expect(pm.response.json().error).to.include("permission");
});</authentication_testing>
<error_testing>
Error Response Testing
错误响应测试
Validation Errors (400)
验证错误(400)
javascript
pm.test("Returns validation error", function () {
pm.response.to.have.status(400);
const json = pm.response.json();
pm.expect(json.error).to.equal("VALIDATION_ERROR");
pm.expect(json.details).to.be.an("array");
pm.expect(json.details[0]).to.have.property("field");
pm.expect(json.details[0]).to.have.property("message");
});javascript
pm.test("返回验证错误", function () {
pm.response.to.have.status(400);
const json = pm.response.json();
pm.expect(json.error).to.equal("VALIDATION_ERROR");
pm.expect(json.details).to.be.an("array");
pm.expect(json.details[0]).to.have.property("field");
pm.expect(json.details[0]).to.have.property("message");
});Not Found (404)
资源不存在(404)
javascript
pm.test("Returns 404 for missing resource", function () {
pm.response.to.have.status(404);
pm.expect(pm.response.json().error).to.equal("NOT_FOUND");
});javascript
pm.test("资源不存在返回404", function () {
pm.response.to.have.status(404);
pm.expect(pm.response.json().error).to.equal("NOT_FOUND");
});Rate Limiting (429)
请求限流(429)
javascript
pm.test("Rate limit headers present", function () {
pm.response.to.have.header("X-RateLimit-Limit");
pm.response.to.have.header("X-RateLimit-Remaining");
pm.response.to.have.header("X-RateLimit-Reset");
});javascript
pm.test("包含限流头信息", function () {
pm.response.to.have.header("X-RateLimit-Limit");
pm.response.to.have.header("X-RateLimit-Remaining");
pm.response.to.have.header("X-RateLimit-Reset");
});Server Errors (5xx)
服务器错误(5xx)
javascript
// Test graceful error handling
pm.test("Error response has request ID", function () {
pm.expect(pm.response.json()).to.have.property("requestId");
});</error_testing>
<ci_integration>
javascript
// 测试优雅错误处理
pm.test("错误响应包含请求ID", function () {
pm.expect(pm.response.json()).to.have.property("requestId");
});</error_testing>
<ci_integration>
CI/CD Integration
CI/CD集成
Newman (Postman CLI)
Newman(Postman CLI)
bash
undefinedbash
undefinedInstall
安装
npm install -g newman
npm install -g newman
Run collection
运行集合
newman run collection.json -e environment.json
newman run collection.json -e environment.json
With reporters
带报告器
newman run collection.json
-e staging.json
--reporters cli,junit
--reporter-junit-export results.xml
-e staging.json
--reporters cli,junit
--reporter-junit-export results.xml
newman run collection.json
-e staging.json
--reporters cli,junit
--reporter-junit-export results.xml
-e staging.json
--reporters cli,junit
--reporter-junit-export results.xml
Specific folder
运行指定文件夹
newman run collection.json --folder "users"
undefinednewman run collection.json --folder "users"
undefinedBruno CLI
Bruno CLI
bash
undefinedbash
undefinedInstall
安装
npm install -g @usebruno/cli
npm install -g @usebruno/cli
Run collection
运行集合
bru run --env staging
bru run --env staging
Specific file
运行指定文件
bru run users/create-user.bru --env local
undefinedbru run users/create-user.bru --env local
undefinedGitHub Actions Example
GitHub Actions示例
yaml
name: API Tests
on:
pull_request:
branches: [main]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Newman
run: npm install -g newman newman-reporter-htmlextra
- name: Run API Tests
run: |
newman run tests/api/collection.json \
-e tests/api/ci.json \
--reporters cli,htmlextra \
--reporter-htmlextra-export report.html
- name: Upload Report
uses: actions/upload-artifact@v4
if: always()
with:
name: api-test-report
path: report.htmlyaml
name: API Tests
on:
pull_request:
branches: [main]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Newman
run: npm install -g newman newman-reporter-htmlextra
- name: Run API Tests
run: |
newman run tests/api/collection.json \
-e tests/api/ci.json \
--reporters cli,htmlextra \
--reporter-htmlextra-export report.html
- name: Upload Report
uses: actions/upload-artifact@v4
if: always()
with:
name: api-test-report
path: report.htmlEnvironment Secrets in CI
CI中的环境密钥
yaml
undefinedyaml
undefinedUse GitHub Secrets for sensitive values
使用GitHub Secrets存储敏感值
- name: Run API Tests
env:
API_KEY: ${{ secrets.STAGING_API_KEY }}
run: |
newman run collection.json
--env-var "apiKey=$API_KEY"
-e staging.json
</ci_integration>
<data_management>- name: Run API Tests
env:
API_KEY: ${{ secrets.STAGING_API_KEY }}
run: |
newman run collection.json
--env-var "apiKey=$API_KEY"
-e staging.json
</ci_integration>
<data_management>Test Data Management
测试数据管理
Data Files (Newman)
数据文件(Newman)
json
// test-data.json
[
{ "email": "user1@test.com", "name": "User One" },
{ "email": "user2@test.com", "name": "User Two" },
{ "email": "user3@test.com", "name": "User Three" }
]bash
undefinedjson
// test-data.json
[
{ "email": "user1@test.com", "name": "User One" },
{ "email": "user2@test.com", "name": "User Two" },
{ "email": "user3@test.com", "name": "User Three" }
]bash
undefinedRun with data iterations
带数据迭代运行
newman run collection.json -d test-data.json -n 3
undefinednewman run collection.json -d test-data.json -n 3
undefinedDynamic Data Generation
动态数据生成
javascript
// Pre-request script
const faker = require("faker"); // Postman has built-in faker
pm.environment.set("randomEmail", pm.variables.replaceIn("{{$randomEmail}}"));
pm.environment.set("randomName", pm.variables.replaceIn("{{$randomFullName}}"));
pm.environment.set("randomUUID", pm.variables.replaceIn("{{$guid}}"));javascript
// 前置请求脚本
const faker = require("faker"); // Postman内置faker
pm.environment.set("randomEmail", pm.variables.replaceIn("{{$randomEmail}}"));
pm.environment.set("randomName", pm.variables.replaceIn("{{$randomFullName}}"));
pm.environment.set("randomUUID", pm.variables.replaceIn("{{$guid}}"));Built-in Dynamic Variables (Postman)
Postman内置动态变量
| Variable | Example Output |
|---|---|
| |
| |
| |
| |
| |
| 变量 | 示例输出 |
|---|---|
| |
| |
| |
| |
| |
Cleanup Scripts
清理脚本
javascript
// Post-request script - cleanup created resources
if (pm.response.code === 201) {
const createdId = pm.response.json().id;
pm.sendRequest({
url: pm.environment.get("baseUrl") + "/users/" + createdId,
method: "DELETE",
header: { "Authorization": "Bearer " + pm.environment.get("authToken") }
}, (err, res) => {
console.log("Cleanup: deleted user " + createdId);
});
}</data_management>
<checklist>javascript
// 请求后脚本 - 清理创建的资源
if (pm.response.code === 201) {
const createdId = pm.response.json().id;
pm.sendRequest({
url: pm.environment.get("baseUrl") + "/users/" + createdId,
method: "DELETE",
header: { "Authorization": "Bearer " + pm.environment.get("authToken") }
}, (err, res) => {
console.log("Cleanup: deleted user " + createdId);
});
}</data_management>
<checklist>API Testing Checklist
API测试检查清单
Before creating collection:
- API documentation reviewed
- Authentication method identified
- Base URLs for all environments defined
- Test data strategy determined
For each endpoint:
- Happy path test (expected input, expected output)
- Required field validation (400 errors)
- Authentication test (401 without token)
- Authorization test (403 wrong permissions)
- Not found test (404 invalid ID)
- Response schema validated
- Response time asserted
Collection organization:
- Requests grouped by resource
- Sequence numbers for dependent requests
- Environments for local/staging/production
- Sensitive values marked as secrets
CI integration:
- Newman/Bruno CLI configured
- GitHub Actions workflow created
- Test reports uploaded as artifacts
- Secrets stored in CI environment </checklist>
| Topic | Reference File | When to Load |
|---|---|---|
| Postman advanced patterns | | Collections, scripting, monitors |
| Bruno workflow | | .bru files, git integration |
| Test case design | | Coverage strategies, edge cases |
| Test data strategies | | Fixtures, dynamic data, cleanup |
| CI/CD pipelines | | Newman, GitHub Actions, reporting |
To load: Ask for the specific topic or check if context suggests it.
</references>
创建集合前:
- 已查阅API文档
- 已确定认证方式
- 已定义所有环境的基础URL
- 已确定测试数据策略
每个端点需满足:
- 正常流程测试(预期输入、预期输出)
- 必填字段验证(400错误)
- 认证测试(无令牌返回401)
- 授权测试(权限错误返回403)
- 资源不存在测试(无效ID返回404)
- 已验证响应schema
- 已断言响应时间
集合组织:
- 请求按资源分组
- 依赖请求有序号标记
- 已配置本地/预发布/生产环境
- 敏感值已标记为机密
CI集成:
- 已配置Newman/Bruno CLI
- 已创建GitHub Actions工作流
- 测试报告已作为工件上传
- 密钥已存储在CI环境中 </checklist>
| 主题 | 参考文件 | 加载场景 |
|---|---|---|
| Postman高级模式 | | 集合管理、脚本编写、监控 |
| Bruno工作流 | | .bru文件、Git集成 |
| 测试用例设计 | | 覆盖策略、边缘场景 |
| 测试数据策略 | | 固定数据、动态数据、清理 |
| CI/CD流水线 | | Newman、GitHub Actions、报告 |
加载方式: 请求指定主题,或根据上下文自动加载。
</references>