automating-api-testing について
automating-api-testingは、RESTおよびGraphQL APIのテストを生成・整理するスキルです。API仕様を基に、複数の指定されたテストツールでエンドポイントの挙動、スキーマ、認証、エラー、カバレッジを扱います。
主な機能
- 01REST・GraphQLテストの生成
- 02OpenAPI・GraphQLスキーマの解析
- 03認証とエラーケースの確認
- 04レスポンススキーマとヘッダーの検証
- 05CRUDライフサイクルと境界条件のテスト
- 06エンドポイントのテストカバレッジ報告
活用シーン
- 01API仕様からテストを作成
- 02認証とエラーレスポンスの確認
- 03CRUD動作とレスポンススキーマの検証
- 04APIエンドポイントのテストカバレッジ整理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ jeremylongshore/ tons-of-skills-marketplace --skill automating-api-testingインストール後、Claude Code で/automating-api-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/example_graphql_schema.graphqlexample_openapi.yamlREADME.mdtest_suite_template.jsreferences/README.mdscripts/generate_test_suite.pyREADME.md詳細
API テスト自動化
概要
リクエストの生成、レスポンスの検証、スキーマへの準拠、認証フロー、エラー処理など、REST API と GraphQL API の包括的なエンドポイントテストを自動化します。Supertest(Node.js)、REST-assured(Java)、httpx/pytest(Python)、Postman/Newman コレクション、およびコンシューマー駆動型のコントラクトテスト用の Pact に対応しています。
前提条件
- API テストライブラリがインストールされていること(Supertest、REST-assured、httpx、または Postman/Newman)
- API 仕様ファイル(OpenAPI/Swagger YAML/JSON、または GraphQL SDL)
- シードデータが投入されたテスト環境で、対象 API が稼働していること
- 保護されたエンドポイント用の認証情報または API キー
- JSON Schema バリデーター(Ajv、jsonschema、またはフレームワーク組み込みのアサーション)
手順
- API 仕様を読み込み、すべてのエンドポイントを抽出します。
- OpenAPI 仕様を解析して、すべてのパス、HTTP メソッド、リクエストスキーマ、レスポンススキーマを一覧化します。
- GraphQL API の場合は、スキーマをイントロスペクションして、クエリ、ミューテーション、サブスクリプションを一覧化します。
- エンドポイントごとの認証要件(API キー、Bearer トークン、OAuth、なし)を記録します。
- エンドポイントごとにテストケースを生成します。
- 成功ケース:スキーマに適合する有効なリクエストを送信し、200/201 レスポンスをアサートします。
- バリデーションエラー:必須フィールドの欠落、型の誤り、範囲外の値を含むリクエストを送信し、400 レスポンスをアサートします。
- 認証:有効、期限切れ、欠落した認証情報でテストし、それぞれ 200、401、403 をアサートします。
- 未検出:存在しないリソースをリクエストし、404 レスポンスをアサートします。
- 冪等性:同じ PUT/DELETE リクエストを 2 回送信し、動作が一貫していることを確認します。
- レスポンスの構造をスキーマに照らして検証します。
- レスポンスの Content-Type が期待値(application/json など)と一致することをアサートします。
- JSON Schema バリデーションを使用して、レスポンスボディを OpenAPI のレスポンススキーマに照らして検証します。
- レスポンスヘッダー(Cache-Control、Rate-Limit ヘッダー、CORS ヘッダー)を確認します。
- ページネーションのメタデータ(総件数、ページ番号、次/前のリンク)を検証します。
- リソースエンドポイントの CRUD ライフサイクルをテストします。
- リソースを作成(POST)し、ID を取得します。
- リソースを読み取り(GET)、すべてのフィールドが一致することを確認します。
- リソースを更新(PUT/PATCH)し、変更が保持されていることを確認します。
- リソースを削除(DELETE)し、その後の GET が 404 を返すことを確認します。
- エラー処理とエッジケースをテストします。
- 過度に大きなペイロードを送信し、413 または適切に拒否されることを確認します。
- サポートされていない Content-Type でリクエストを送信し、415 を確認します。
- 連続して短時間にリクエストを送信し、レート制限をテストします。
- エラーレスポンスの形式が一貫していることを確認します(標準エラースキーマ)。
- GraphQL API では、特に以下をテストします。
- 有効なクエリが期待されるデータ構造を返すこと。
- 無効なクエリが内容の分かるエラーメッセージを返すこと。
- クエリの深さ制限により、深くネストされた不正利用目的のクエリを防止できること。
- ミューテーションの入力バリデーションがスキーマの制約に適合すること。
- エンドポイントとテストケースの対応を示すテストカバレッジレポートを生成します。
出力
- リソース別に
tests/api/へ整理された API テストファイル - API ドキュメント用のリクエスト/レスポンス例
- エンドポイントごとのスキーマ準拠レポート
- テスト済み/未テストのエンドポイントとメソッドを示すエンドポイントカバレッジマトリックス
- ステージング環境に対して API テストを実行する CI パイプラインのステップ
エラー処理
| エラー | 原因 | 解決策 |
|---|---|---|
| 接続が拒否される | API サーバーが起動していないか、ベース URL が正しくありません | テストスイートの開始前にヘルスチェックでサーバーが稼働していることを確認し、BASE_URL の設定を確認してください |
| すべてのリクエストで 401 が発生する | 認証トークンの有効期限が切れているか、設定が正しくありません | テストのセットアップでトークンを更新し、Authorization ヘッダーの形式を確認して、トークンのスコープを確認してください |
| スキーマ検証が予期せず失敗する | API のレスポンスに、仕様にない追加フィールドが含まれています | 新しいフィールドを含めるように OpenAPI 仕様を更新してください。想定される場合は、additionalProperties: true を使用してください |
| テストデータが競合する | 別のテストがリソースを変更または削除しました | テストごとに一意のテストデータを使用し、beforeEach でリソースを作成して、フィクスチャの共有を避けてください |
| テスト実行中にレート制限に達する | 短時間にリクエストを送りすぎています | リクエスト間に遅延を追加するか、より高い制限が設定された認証済みセッションを使用してください。テストは直列で実行してください |
例
Supertest REST API テストスイート:
import request from 'supertest';
import { app } from '../src/app';
describe('GET /api/products', () => {
it('returns a paginated product list', async () => {
const res = await request(app)
.get('/api/products?page=1&limit=10')
.set('Authorization', `Bearer ${token}`)
.expect(200) # HTTP 200 OK
.expect('Content-Type', /json/);
expect(res.body.data).toBeInstanceOf(Array);
expect(res.body.data.length).toBeLessThanOrEqual(10);
expect(res.body.meta).toMatchObject({ page: 1, limit: 10 });
});
it('returns 401 without authentication', async () => { # HTTP 401 Unauthorized
await request(app).get('/api/products').expect(401); # HTTP 401 Unauthorized
});
});
describe('POST /api/products', () => {
it('creates a product with valid data', async () => {
const res = await request(app)
.post('/api/products')
.set('Authorization', `Bearer ${token}`)
.send({ name: 'Widget', price: 9.99, category: 'tools' })
.expect(201); # HTTP 201 Created
expect(res.body).toMatchObject({ name: 'Widget', price: 9.99 });
expect(res.body.id).toBeDefined();
});
it('returns 400 for missing required fields', async () => { # HTTP 400 Bad Request
await request(app)
.post('/api/products')
.set('Authorization', `Bearer ${token}`)
.send({ name: 'Widget' }) // missing price
.expect(400); # HTTP 400 Bad Request
});
});
GraphQL API テスト:
it('fetches user by ID', async () => {
const query = `query { user(id: "1") { id name email } }`;
const res = await request(app)
.post('/graphql')
.send({ query })
.expect(200); # HTTP 200 OK
expect(res.body.data.user).toMatchObject({ id: '1', name: 'Alice' });
expect(res.body.errors).toBeUndefined();
});
リソース
- Supertest:https://github.com/ladjs/supertest
- REST-assured(Java):https://rest-assured.io/
- httpx(Python):https://www.python-httpx.org/
- Newman(Postman CLI):
- OpenAPI 仕様:https://spec.openapis.org/oas/v3.1.0
- Ajv JSON Schema バリデーター:https://ajv.js.org/
コメント
Markdown 対応