api-testing-patterns
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAPI Testing Patterns
API测试模式
<default_to_action>
When testing APIs or designing API test strategy:
- IDENTIFY testing level: contract, integration, or component
- TEST the contract, not implementation (consumer perspective)
- VALIDATE auth, input, errors, idempotency, concurrency
- AUTOMATE in CI/CD with schema validation
- 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测试策略时:
- 确定测试层级:契约测试、集成测试或组件测试
- 测试契约而非实现(从消费者视角出发)
- 验证认证、输入、错误处理、幂等性、并发情况
- 在CI/CD中结合Schema验证实现自动化
- 监控生产环境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
测试层级
| Level | Purpose | Dependencies | Speed |
|---|---|---|---|
| Contract | Provider-consumer agreement | None | Fast |
| Component | API in isolation | Mocked | Fast |
| Integration | Real dependencies | Database, services | Slower |
| 层级 | 目的 | 依赖项 | 速度 |
|---|---|---|---|
| 契约测试 | 验证提供者与消费者的约定 | 无 | 快 |
| 组件测试 | 隔离测试API | 依赖Mock | 快 |
| 集成测试 | 测试真实依赖 | 数据库、服务 | 慢 |
Critical Test Scenarios
关键测试场景
| Scenario | Must Test | Example |
|---|---|---|
| Auth | 401/403 handling | Expired token, wrong user |
| Input | 400 validation | Missing fields, wrong types |
| Errors | 500 graceful handling | DB down, timeout |
| Idempotency | Duplicate prevention | Same idempotency key |
| Concurrency | Race conditions | Parallel 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协作
- : Validate contracts, detect breaking changes
qe-api-contract-validator - : Generate tests from OpenAPI spec
qe-test-generator - : Load test endpoints
qe-performance-tester - : API security testing
qe-security-scanner
- : 验证契约,检测破坏性变更
qe-api-contract-validator - : 从OpenAPI规范生成测试用例
qe-test-generator - : 对端点进行负载测试
qe-performance-tester - : API安全测试
qe-security-scanner
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 resultsaqe/api-testing/
├── contracts/* - API contract definitions
├── generated-tests/* - Generated test suites
├── validation/* - Contract validation results
└── performance/* - Load test resultsFleet 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质量。