mcpField
A
automating-api-testing

automating-api-testing

github.com/jeremylongshoreテスト・品質2.9k68 回インストール2 日前に更新
リポジトリ

automating-api-testing について

automating-api-testingは、RESTおよびGraphQL APIのテストを生成・整理するスキルです。API仕様を基に、複数の指定されたテストツールでエンドポイントの挙動、スキーマ、認証、エラー、カバレッジを扱います。

主な機能

  1. 01REST・GraphQLテストの生成
  2. 02OpenAPI・GraphQLスキーマの解析
  3. 03認証とエラーケースの確認
  4. 04レスポンススキーマとヘッダーの検証
  5. 05CRUDライフサイクルと境界条件のテスト
  6. 06エンドポイントのテストカバレッジ報告

活用シーン

  1. 01API仕様からテストを作成
  2. 02認証とエラーレスポンスの確認
  3. 03CRUD動作とレスポンススキーマの検証
  4. 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.graphql
example_openapi.yaml
README.md
test_suite_template.js
references/
README.md
scripts/
generate_test_suite.py
README.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、またはフレームワーク組み込みのアサーション)

手順

  1. API 仕様を読み込み、すべてのエンドポイントを抽出します。
    • OpenAPI 仕様を解析して、すべてのパス、HTTP メソッド、リクエストスキーマ、レスポンススキーマを一覧化します。
    • GraphQL API の場合は、スキーマをイントロスペクションして、クエリ、ミューテーション、サブスクリプションを一覧化します。
    • エンドポイントごとの認証要件(API キー、Bearer トークン、OAuth、なし)を記録します。
  2. エンドポイントごとにテストケースを生成します。
    • 成功ケース:スキーマに適合する有効なリクエストを送信し、200/201 レスポンスをアサートします。
    • バリデーションエラー:必須フィールドの欠落、型の誤り、範囲外の値を含むリクエストを送信し、400 レスポンスをアサートします。
    • 認証:有効、期限切れ、欠落した認証情報でテストし、それぞれ 200、401、403 をアサートします。
    • 未検出:存在しないリソースをリクエストし、404 レスポンスをアサートします。
    • 冪等性:同じ PUT/DELETE リクエストを 2 回送信し、動作が一貫していることを確認します。
  3. レスポンスの構造をスキーマに照らして検証します。
    • レスポンスの Content-Type が期待値(application/json など)と一致することをアサートします。
    • JSON Schema バリデーションを使用して、レスポンスボディを OpenAPI のレスポンススキーマに照らして検証します。
    • レスポンスヘッダー(Cache-Control、Rate-Limit ヘッダー、CORS ヘッダー)を確認します。
    • ページネーションのメタデータ(総件数、ページ番号、次/前のリンク)を検証します。
  4. リソースエンドポイントの CRUD ライフサイクルをテストします。
    • リソースを作成(POST)し、ID を取得します。
    • リソースを読み取り(GET)、すべてのフィールドが一致することを確認します。
    • リソースを更新(PUT/PATCH)し、変更が保持されていることを確認します。
    • リソースを削除(DELETE)し、その後の GET が 404 を返すことを確認します。
  5. エラー処理とエッジケースをテストします。
    • 過度に大きなペイロードを送信し、413 または適切に拒否されることを確認します。
    • サポートされていない Content-Type でリクエストを送信し、415 を確認します。
    • 連続して短時間にリクエストを送信し、レート制限をテストします。
    • エラーレスポンスの形式が一貫していることを確認します(標準エラースキーマ)。
  6. GraphQL API では、特に以下をテストします。
    • 有効なクエリが期待されるデータ構造を返すこと。
    • 無効なクエリが内容の分かるエラーメッセージを返すこと。
    • クエリの深さ制限により、深くネストされた不正利用目的のクエリを防止できること。
    • ミューテーションの入力バリデーションがスキーマの制約に適合すること。
  7. エンドポイントとテストケースの対応を示すテストカバレッジレポートを生成します。

出力

  • リソース別に 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();
});

リソース

コメント