qe-api-testing-patterns について
qe-api-testing-patternsは、APIをテストするチームやテスト戦略を設計する人向けのスキルです。契約・コンポーネント・統合テストと、認証、入力検証、エラー、冪等性、並行処理のパターンを扱います。
主な機能
- 01契約・コンポーネント・統合テスト
- 02コンシューマー視点の契約検証
- 03認証と入力検証のテスト
- 04エラーと冪等性のシナリオ
- 05並行処理とCRUDのパターン
- 06APIテスト自動化のガイド
活用シーン
- 01マイクロサービスの契約テスト
- 02RESTやGraphQLの挙動検証
- 03認証と障害処理の確認
- 04CI/CD向けAPIテストの計画
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ proffesor-for-testing/ agentic-qe --skill qe-api-testing-patternsインストール後、Claude Code で/qe-api-testing-patternsを入力して読み込まれたか確認します。
詳細
API テストパターン
<default_to_action> API をテストする場合、または API テスト戦略を設計する場合:
- テストレベルを特定します:コントラクト、インテグレーション、またはコンポーネント
- 実装ではなく、コントラクトをテストします(コンシューマーの視点)
- 認証、入力、エラー、冪等性、並行性を検証します
- スキーマ検証を使って CI/CD で自動化します
- 本番環境の API を監視し、コントラクトのドリフトを検出します
パターンのクイック選択:
- マイクロサービス → コンシューマー主導コントラクト(Pact)
- REST API → CRUD +ページネーション+フィルタリングのテスト
- GraphQL → クエリ検証+複雑度制限
- 外部依存関係 → コンポーネントテストでモックを使用
- パフォーマンス → 重要なエンドポイントの負荷テスト
重要な成功要因:
- API はコントラクトです。コンシューマーの視点でテストします
- 成功パスだけでなく、必ずエラーシナリオもテストします
- 破壊的変更を防ぐため、API テストをバージョン管理します </default_to_action>
クイックリファレンスカード
使用する場面
- REST API または GraphQL API のテスト
- マイクロサービスのコントラクト検証
- API テスト戦略の設計
- API の破壊的変更の防止
テストレベル
| レベル | 目的 | 依存関係 | 速度 |
|---|---|---|---|
| コントラクト | プロバイダーとコンシューマー間の合意 | なし | 高速 |
| コンポーネント | 独立した API | モック | 高速 |
| インテグレーション | 実際の依存関係 | データベース、サービス | 低速 |
重要なテストシナリオ
| シナリオ | 必須のテスト | 例 |
|---|---|---|
| 認証 | 401/403 の処理 | トークンの期限切れ、ユーザーの誤り |
| 入力 | 400 の検証 | 必須フィールドの欠落、型の誤り |
| エラー | 500 の適切な処理 | DB の停止、タイムアウト |
| 冪等性 | 重複の防止 | 同じ冪等性キー |
| 並行性 | 競合状態 | 並列チェックアウト |
ツール
- コントラクト:Pact、Spring Cloud Contract
- REST:Supertest、REST-assured、Playwright
- 負荷:k6、Artillery、JMeter
エージェントの連携
qe-api-contract-validator:コントラクトを検証し、破壊的変更を検出しますqe-test-generator:OpenAPI 仕様からテストを生成しますqe-performance-tester:エンドポイントの負荷テストを実施しますqe-security-scanner:API のセキュリティテストを実施します
コントラクトテスト
パターン:コンシューマー主導コントラクト
// 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)
});
});
使用する場面: マイクロサービス、分散システム、サードパーティ統合
重要なテストパターン
認証と認可
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);
});
});
入力検証
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);
});
});
冪等性
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
});
並行性
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 パターン
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);
});
});
ベストプラクティス
✅ 推奨事項
- コンシューマーの視点でテストします
- スキーマ検証を使用します(厳密な値の検証ではなく)
- エラーシナリオを徹底的にテストします
- API テストをバージョン管理します
- CI/CD で自動化します
❌ 避けること
- コントラクトではなく実装をテストすること
- HTTP のセマンティクス(ステータスコード)を無視すること
- ネガティブテストを行わないこと
- フィールドの順序や余分なフィールドに対してアサーションを行うこと
- テストに時間がかかること(外部サービスをモックします)
エージェントを活用した API テスト
// 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");
エージェント連携のヒント
メモリ名前空間
aqe/api-testing/
├── contracts/* - API contract definitions
├── generated-tests/* - Generated test suites
├── validation/* - Contract validation results
└── performance/* - Load test results
フリート連携
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'] }
]
});
関連スキル
- agentic-quality-engineering - エージェントを活用した API テスト
- tdd-london-chicago - API テストにおけるロンドン学派
- performance-testing - API の負荷テスト
- security-testing - API のセキュリティ検証
- contract-testing - コンシューマー主導コントラクトの詳細
覚えておくこと
API テストとは、実装ではなくコントラクトと動作を検証することです。正しいレスポンス、適切なエラー処理、許容できるパフォーマンスなど、コンシューマーにとって重要な点に注目します。
エージェントを活用する場合: エージェントはコントラクト検証を自動化し、仕様から包括的なテストスイートを生成して、本番環境の API を監視し、ドリフトを検出します。エージェントを活用して、大規模な API 品質の維持に役立てましょう。
コメント
Markdown 対応