api-testing-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API Testing Patterns

API测试模式

<default_to_action> When testing APIs or designing API test strategy:
  1. IDENTIFY testing level: contract, integration, or component
  2. TEST the contract, not implementation (consumer perspective)
  3. VALIDATE auth, input, errors, idempotency, concurrency
  4. AUTOMATE in CI/CD with schema validation
  5. MONITOR production APIs for contract drift
Quick Pattern Selection:
  • Microservices → Consumer-driven contracts (Pact)
  • REST APIs → CRUD + pagination + filtering tests
  • GraphQL → Query validation + complexity limits
  • External deps → Mock with component testing
  • Performance → Load test critical endpoints
Critical Success Factors:
  • APIs are contracts - test from consumer perspective
  • Always test error scenarios, not just happy paths
  • Version your API tests to prevent breaking changes </default_to_action>
<default_to_action> 当测试API或设计API测试策略时:
  1. 确定测试层级:契约测试、集成测试或组件测试
  2. 测试契约而非实现(从消费者视角出发)
  3. 验证认证、输入、错误处理、幂等性、并发情况
  4. 在CI/CD中结合Schema验证实现自动化
  5. 监控生产环境API的契约漂移情况
快速模式选择:
  • 微服务 → 消费者驱动契约(Pact)
  • REST API → CRUD + 分页 + 过滤测试
  • GraphQL → 查询验证 + 复杂度限制
  • 外部依赖 → 组件测试结合Mock
  • 性能 → 对关键端点进行负载测试
关键成功因素:
  • API即契约 - 从消费者视角进行测试
  • 务必测试错误场景,而非仅测试正常路径
  • 对API测试进行版本控制,以防止破坏性变更 </default_to_action>

Quick Reference Card

快速参考卡片

When to Use

适用场景

  • Testing REST or GraphQL APIs
  • Validating microservice contracts
  • Designing API test strategies
  • Preventing breaking API changes
  • 测试REST或GraphQL API
  • 验证微服务契约
  • 设计API测试策略
  • 防止API出现破坏性变更

Testing Levels

测试层级

LevelPurposeDependenciesSpeed
ContractProvider-consumer agreementNoneFast
ComponentAPI in isolationMockedFast
IntegrationReal dependenciesDatabase, servicesSlower
层级目的依赖项速度
契约测试验证提供者与消费者的约定
组件测试隔离测试API依赖Mock
集成测试测试真实依赖数据库、服务

Critical Test Scenarios

关键测试场景

ScenarioMust TestExample
Auth401/403 handlingExpired token, wrong user
Input400 validationMissing fields, wrong types
Errors500 graceful handlingDB down, timeout
IdempotencyDuplicate preventionSame idempotency key
ConcurrencyRace conditionsParallel checkout
场景必须测试示例
认证401/403处理过期令牌、错误用户
输入400验证缺失字段、错误类型
错误500优雅处理数据库宕机、超时
幂等性防止重复操作相同幂等键
并发竞争条件并行结账

Tools

工具

  • Contract: Pact, Spring Cloud Contract
  • REST: Supertest, REST-assured, Playwright
  • Load: k6, Artillery, JMeter
  • 契约测试: Pact, Spring Cloud Contract
  • REST测试: Supertest, REST-assured, Playwright
  • 负载测试: k6, Artillery, JMeter

Agent Coordination

Agent协作

  • qe-api-contract-validator
    : Validate contracts, detect breaking changes
  • qe-test-generator
    : Generate tests from OpenAPI spec
  • qe-performance-tester
    : Load test endpoints
  • qe-security-scanner
    : API security testing

  • qe-api-contract-validator
    : 验证契约,检测破坏性变更
  • qe-test-generator
    : 从OpenAPI规范生成测试用例
  • qe-performance-tester
    : 对端点进行负载测试
  • qe-security-scanner
    : API安全测试

Contract Testing

契约测试

Pattern: Consumer-Driven Contracts
javascript
// Consumer defines expectations
const contract = {
  request: { method: 'POST', path: '/orders', body: { productId: 'abc', quantity: 2 } },
  response: { status: 201, body: { orderId: 'string', total: 'number' } }
};

// Provider must fulfill
test('order API meets contract', async () => {
  const response = await api.post('/orders', { productId: 'abc', quantity: 2 });

  expect(response.status).toBe(201);
  expect(response.body).toMatchSchema({
    orderId: expect.any(String),
    total: expect.any(Number)
  });
});
When: Microservices, distributed systems, third-party integrations

模式:消费者驱动契约
javascript
// Consumer defines expectations
const contract = {
  request: { method: 'POST', path: '/orders', body: { productId: 'abc', quantity: 2 } },
  response: { status: 201, body: { orderId: 'string', total: 'number' } }
};

// Provider must fulfill
test('order API meets contract', async () => {
  const response = await api.post('/orders', { productId: 'abc', quantity: 2 });

  expect(response.status).toBe(201);
  expect(response.body).toMatchSchema({
    orderId: expect.any(String),
    total: expect.any(Number)
  });
});
适用场景: 微服务、分布式系统、第三方集成

Critical Test Patterns

关键测试模式

Authentication & Authorization

认证与授权

javascript
describe('Auth', () => {
  it('rejects without token', async () => {
    expect((await api.get('/orders')).status).toBe(401);
  });

  it('rejects expired token', async () => {
    const expired = generateExpiredToken();
    expect((await api.get('/orders', { headers: { Authorization: `Bearer ${expired}` } })).status).toBe(401);
  });

  it('blocks cross-user access', async () => {
    const userAToken = generateToken({ userId: 'A' });
    expect((await api.get('/orders/user-B-order', { headers: { Authorization: `Bearer ${userAToken}` } })).status).toBe(403);
  });
});
javascript
describe('Auth', () => {
  it('rejects without token', async () => {
    expect((await api.get('/orders')).status).toBe(401);
  });

  it('rejects expired token', async () => {
    const expired = generateExpiredToken();
    expect((await api.get('/orders', { headers: { Authorization: `Bearer ${expired}` } })).status).toBe(401);
  });

  it('blocks cross-user access', async () => {
    const userAToken = generateToken({ userId: 'A' });
    expect((await api.get('/orders/user-B-order', { headers: { Authorization: `Bearer ${userAToken}` } })).status).toBe(403);
  });
});

Input Validation

输入验证

javascript
describe('Validation', () => {
  it('validates required fields', async () => {
    const response = await api.post('/orders', { quantity: 2 }); // Missing productId
    expect(response.status).toBe(400);
    expect(response.body.errors).toContain('productId is required');
  });

  it('validates types', async () => {
    expect((await api.post('/orders', { productId: 'abc', quantity: 'two' })).status).toBe(400);
  });

  it('validates ranges', async () => {
    expect((await api.post('/orders', { productId: 'abc', quantity: -5 })).status).toBe(400);
  });
});
javascript
describe('Validation', () => {
  it('validates required fields', async () => {
    const response = await api.post('/orders', { quantity: 2 }); // Missing productId
    expect(response.status).toBe(400);
    expect(response.body.errors).toContain('productId is required');
  });

  it('validates types', async () => {
    expect((await api.post('/orders', { productId: 'abc', quantity: 'two' })).status).toBe(400);
  });

  it('validates ranges', async () => {
    expect((await api.post('/orders', { productId: 'abc', quantity: -5 })).status).toBe(400);
  });
});

Idempotency

幂等性

javascript
it('prevents duplicates with idempotency key', async () => {
  const key = 'unique-123';
  const data = { productId: 'abc', quantity: 2 };

  const r1 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });
  const r2 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });

  expect(r1.body.orderId).toBe(r2.body.orderId); // Same order
});
javascript
it('prevents duplicates with idempotency key', async () => {
  const key = 'unique-123';
  const data = { productId: 'abc', quantity: 2 };

  const r1 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });
  const r2 = await api.post('/orders', data, { headers: { 'Idempotency-Key': key } });

  expect(r1.body.orderId).toBe(r2.body.orderId); // Same order
});

Concurrency

并发

javascript
it('handles race condition on inventory', async () => {
  const promises = Array(10).fill().map(() =>
    api.post('/orders', { productId: 'abc', quantity: 1 })
  );
  const responses = await Promise.all(promises);
  const successful = responses.filter(r => r.status === 201);

  const inventory = await db.inventory.findById('abc');
  expect(inventory.quantity).toBe(initialQuantity - successful.length);
});

javascript
it('handles race condition on inventory', async () => {
  const promises = Array(10).fill().map(() =>
    api.post('/orders', { productId: 'abc', quantity: 1 })
  );
  const responses = await Promise.all(promises);
  const successful = responses.filter(r => r.status === 201);

  const inventory = await db.inventory.findById('abc');
  expect(inventory.quantity).toBe(initialQuantity - successful.length);
});

REST CRUD Pattern

REST CRUD模式

javascript
describe('Product CRUD', () => {
  let productId;

  it('CREATE', async () => {
    const r = await api.post('/products', { name: 'Widget', price: 10 });
    expect(r.status).toBe(201);
    productId = r.body.id;
  });

  it('READ', async () => {
    const r = await api.get(`/products/${productId}`);
    expect(r.body.name).toBe('Widget');
  });

  it('UPDATE', async () => {
    const r = await api.put(`/products/${productId}`, { price: 12 });
    expect(r.body.price).toBe(12);
  });

  it('DELETE', async () => {
    expect((await api.delete(`/products/${productId}`)).status).toBe(204);
    expect((await api.get(`/products/${productId}`)).status).toBe(404);
  });
});

javascript
describe('Product CRUD', () => {
  let productId;

  it('CREATE', async () => {
    const r = await api.post('/products', { name: 'Widget', price: 10 });
    expect(r.status).toBe(201);
    productId = r.body.id;
  });

  it('READ', async () => {
    const r = await api.get(`/products/${productId}`);
    expect(r.body.name).toBe('Widget');
  });

  it('UPDATE', async () => {
    const r = await api.put(`/products/${productId}`, { price: 12 });
    expect(r.body.price).toBe(12);
  });

  it('DELETE', async () => {
    expect((await api.delete(`/products/${productId}`)).status).toBe(204);
    expect((await api.get(`/products/${productId}`)).status).toBe(404);
  });
});

Best Practices

最佳实践

✅ Do This

✅ 推荐做法

  • Test from consumer perspective
  • Use schema validation (not exact values)
  • Test error scenarios extensively
  • Version API tests
  • Automate in CI/CD
  • 从消费者视角进行测试
  • 使用Schema验证(而非精确值)
  • 全面测试错误场景
  • 对API测试进行版本控制
  • 在CI/CD中实现自动化

❌ Avoid This

❌ 避免做法

  • Testing implementation, not contract
  • Ignoring HTTP semantics (status codes)
  • No negative testing
  • Asserting on field order or extra fields
  • Slow tests (mock external services)

  • 测试实现细节而非契约
  • 忽略HTTP语义(状态码)
  • 不进行负面测试
  • 断言字段顺序或额外字段
  • 慢测试(对外部服务使用Mock)

Agent-Assisted API Testing

Agent辅助API测试

typescript
// Validate contracts
await Task("Contract Validation", {
  spec: 'openapi.yaml',
  endpoint: '/orders',
  checkBreakingChanges: true
}, "qe-api-contract-validator");

// Generate tests from spec
await Task("Generate API Tests", {
  spec: 'openapi.yaml',
  coverage: 'comprehensive',
  include: ['happy-paths', 'input-validation', 'auth-scenarios', 'error-handling']
}, "qe-test-generator");

// Load test
await Task("API Load Test", {
  endpoint: '/orders',
  rps: 1000,
  duration: '5min'
}, "qe-performance-tester");

// Security scan
await Task("API Security Scan", {
  spec: 'openapi.yaml',
  checks: ['sql-injection', 'xss', 'broken-auth', 'rate-limiting']
}, "qe-security-scanner");

typescript
// Validate contracts
await Task("Contract Validation", {
  spec: 'openapi.yaml',
  endpoint: '/orders',
  checkBreakingChanges: true
}, "qe-api-contract-validator");

// Generate tests from spec
await Task("Generate API Tests", {
  spec: 'openapi.yaml',
  coverage: 'comprehensive',
  include: ['happy-paths', 'input-validation', 'auth-scenarios', 'error-handling']
}, "qe-test-generator");

// Load test
await Task("API Load Test", {
  endpoint: '/orders',
  rps: 1000,
  duration: '5min'
}, "qe-performance-tester");

// Security scan
await Task("API Security Scan", {
  spec: 'openapi.yaml',
  checks: ['sql-injection', 'xss', 'broken-auth', 'rate-limiting']
}, "qe-security-scanner");

Agent Coordination Hints

Agent协作提示

Memory Namespace

内存命名空间

aqe/api-testing/
├── contracts/*        - API contract definitions
├── generated-tests/*  - Generated test suites
├── validation/*       - Contract validation results
└── performance/*      - Load test results
aqe/api-testing/
├── contracts/*        - API contract definitions
├── generated-tests/*  - Generated test suites
├── validation/*       - Contract validation results
└── performance/*      - Load test results

Fleet Coordination

集群协作

typescript
const apiFleet = await FleetManager.coordinate({
  strategy: 'contract-testing',
  agents: ['qe-api-contract-validator', 'qe-test-generator', 'qe-test-executor'],
  topology: 'mesh'
});

await apiFleet.execute({
  services: [
    { name: 'orders-api', consumers: ['checkout-ui', 'admin-api'] },
    { name: 'payment-api', consumers: ['orders-api'] }
  ]
});

typescript
const apiFleet = await FleetManager.coordinate({
  strategy: 'contract-testing',
  agents: ['qe-api-contract-validator', 'qe-test-generator', 'qe-test-executor'],
  topology: 'mesh'
});

await apiFleet.execute({
  services: [
    { name: 'orders-api', consumers: ['checkout-ui', 'admin-api'] },
    { name: 'payment-api', consumers: ['orders-api'] }
  ]
});

Related Skills

相关技能

  • agentic-quality-engineering - API testing with agents
  • tdd-london-chicago - London school for API testing
  • performance-testing - API load testing
  • security-testing - API security validation
  • contract-testing - Consumer-driven contracts deep dive

  • agentic-quality-engineering - 基于Agent的质量工程中的API测试
  • tdd-london-chicago - 适用于API测试的伦敦学派TDD
  • performance-testing - API负载测试
  • security-testing - API安全验证
  • contract-testing - 消费者驱动契约深度解析

Remember

要点回顾

API testing = verifying contracts and behavior, not implementation. Focus on what matters to consumers: correct responses, proper error handling, acceptable performance.
With Agents: Agents automate contract validation, generate comprehensive test suites from specs, and monitor production APIs for drift. Use agents to maintain API quality at scale.
API测试 = 验证契约与行为,而非实现细节。聚焦于消费者关注的内容:正确的响应、恰当的错误处理、可接受的性能。
借助Agent: Agent可自动完成契约验证、从规范生成全面测试套件,并监控生产环境API的契约漂移。使用Agent可在大规模场景下维护API质量。