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对比

FeaturePostmanBruno
StorageCloud/LocalGit-native (.bru files)
CollaborationTeam syncGit branches
PricingFree tier + paidFree and open source
OfflineDesktop appFull offline
ScriptingJavaScriptJavaScript
CI/CDNewman CLIBruno CLI
SchemaJSONPlain text .bru
Best ForTeams, API documentationGit workflows, privacy
特性PostmanBruno
存储方式云端/本地Git原生(.bru文件)
协作方式团队实时同步Git分支协作
定价免费版+付费版免费开源
离线支持桌面应用支持完全离线可用
脚本支持JavaScriptJavaScript
CI/CD集成Newman CLIBruno 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.bru
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.bru

Naming Conventions

命名规范

ElementConventionExample
Folderskebab-case, plural
users
,
auth-flows
Requestsverb-noun
create-user
,
get-orders
VariablescamelCase
{{baseUrl}}
,
{{authToken}}
Environmentslowercase
local
,
staging
,
production
元素规范示例
文件夹短横线命名、复数形式
users
,
auth-flows
请求动词-名词结构
create-user
,
get-orders
变量小驼峰命名
{{baseUrl}}
,
{{authToken}}
环境全小写
local
,
staging
,
production

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
undefined
bash
undefined

Install

安装

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
newman run collection.json
-e staging.json
--reporters cli,junit
--reporter-junit-export results.xml

Specific folder

运行指定文件夹

newman run collection.json --folder "users"
undefined
newman run collection.json --folder "users"
undefined

Bruno CLI

Bruno CLI

bash
undefined
bash
undefined

Install

安装

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
undefined
bru run users/create-user.bru --env local
undefined

GitHub 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.html
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.html

Environment Secrets in CI

CI中的环境密钥

yaml
undefined
yaml
undefined

Use 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
undefined
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
undefined

Run with data iterations

带数据迭代运行

newman run collection.json -d test-data.json -n 3
undefined
newman run collection.json -d test-data.json -n 3
undefined

Dynamic 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内置动态变量

VariableExample Output
{{$guid}}
a8b2c3d4-e5f6-7890-abcd-ef1234567890
{{$timestamp}}
1612345678
{{$randomEmail}}
test.user@example.com
{{$randomInt}}
42
{{$randomFullName}}
John Smith
变量示例输出
{{$guid}}
a8b2c3d4-e5f6-7890-abcd-ef1234567890
{{$timestamp}}
1612345678
{{$randomEmail}}
test.user@example.com
{{$randomInt}}
42
{{$randomFullName}}
John Smith

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>
<references> For detailed patterns, load the appropriate reference:
TopicReference FileWhen to Load
Postman advanced patterns
reference/postman-patterns.md
Collections, scripting, monitors
Bruno workflow
reference/bruno-patterns.md
.bru files, git integration
Test case design
reference/test-design.md
Coverage strategies, edge cases
Test data strategies
reference/data-management.md
Fixtures, dynamic data, cleanup
CI/CD pipelines
reference/ci-integration.md
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>
<references> 如需详细模式,请加载对应参考文档:
主题参考文件加载场景
Postman高级模式
reference/postman-patterns.md
集合管理、脚本编写、监控
Bruno工作流
reference/bruno-patterns.md
.bru文件、Git集成
测试用例设计
reference/test-design.md
覆盖策略、边缘场景
测试数据策略
reference/data-management.md
固定数据、动态数据、清理
CI/CD流水线
reference/ci-integration.md
Newman、GitHub Actions、报告
加载方式: 请求指定主题,或根据上下文自动加载。 </references>