APIテストのやり方|観点とチェックリスト

「このAPIのテストをお願い」と仕様書やOpenAPI定義を渡されたものの、何をどこまで確認すればいいのか手が止まる。そんな方に向けて、この記事ではAPIテストのやり方を観点の全体像から具体的なチェックリストまで体系立てて解説します。
画面テストは手動でこなしてきたけれど、REST APIそのものの検証は我流。ステータスコードとレスポンスをなんとなく目視しているだけで、異常系や認証まわりに漏れがないか不安。そうした状態から、レビューや引き継ぎで「観点が整理されている」と信頼される状態を目指します。
APIテストとは何か、なぜ画面テストとは別に必要か
APIテストとは
APIテストとは、画面を介さずにリクエストとレスポンスを直接検証するテストです。特定のエンドポイントに対してパラメータやヘッダを組み立てて送信し、返ってきたステータスコード・レスポンスボディ・ヘッダが仕様どおりかを確認します。
画面テストが「ユーザーが見る結果」を検証するのに対し、APIテストは「サーバーが返す契約」を検証します。両者は対象が違うため、片方だけでは不十分です。
テストピラミッドでの位置づけ
テスト全体の中での位置づけは、テストピラミッドで整理できます。吉井健文『フロントエンド開発テスト入門』では、テストピラミッド型を「下層を多くすることで安定かつ費用対効果の高いテスト戦略」と説明します(Mike Cohn 提唱、2009年)。
- 下層(単体テスト): 関数・クラス単位。数が多く高速で安定
- 中段(API・統合テスト): 複数の部品を結合して振る舞いを検証
- 上層(E2Eテスト): 画面を通した一連の操作。忠実だが遅く壊れやすい
APIテストはこの中段に位置し、単体テストより広い範囲を、E2Eより速く安定して検証できる費用対効果の高い層です。E2Eの前提となる考え方は、E2Eテストの基礎を確認すると全体像がつかめます。
画面テストだけでは漏れる領域
なぜ画面テストだけでは漏れるのか。画面には「入力できない値」「押せないボタン」があり、UIが不正な操作を物理的に防いでしまうからです。しかしAPIは、画面を経由しないリクエストを直接受け付けます。
画面で防いでいるつもりのバリデーション・権限・エラー応答は、APIを直接叩くと簡単にすり抜けることがあります。ここを潰すのがAPIテストの役割です。
Khorikov『単体テストの考え方/使い方』は、統合テストの役割を「単体テストで網羅できない部分を埋める」ことと述べ、プロセス外依存との統合を検証できる点をメリットに挙げます。APIテストはまさにこの統合の層を担います。
| 観点 | UI(画面)テスト | APIテスト |
|---|---|---|
| 対象 | 画面表示・操作結果 | リクエスト/レスポンスの中身 |
| 検出できるバグ | 表示崩れ・導線の不備 | バリデーション漏れ・権限不備・エラー応答の誤り |
| 実行速度 | 遅い(描画を伴う) | 速い(通信のみ) |
| 安定性 | 崩れやすい | 比較的安定 |
APIテストのやり方|観点の全体像(7つのカテゴリ)
7つのカテゴリを地図として押さえる
APIテストの観点は、大きく7つのカテゴリに整理すると漏れを防げます。まず全体像を地図として押さえ、以降の章で個別に掘り下げます。
- ①正常系: 仕様どおりの入力で、期待どおりのレスポンスが返るか
- ②異常系・エラー系: 不正な入力や欠落に対し、適切なエラーが返るか
- ③バリデーション・境界値: 値の範囲・型・必須の判定が正しいか
- ④認証・認可: 誰がアクセスでき、何を許すかが制御されているか
- ⑤ステータスコード/レスポンス検証: 操作に応じたコードとボディが返るか
- ⑥冪等性・副作用: 同じリクエストを複数回送っても状態が壊れないか
- ⑦パフォーマンス・レート制限: 想定負荷や制限超過時の挙動が妥当か
正常系だけを試して安心するのではなく、7カテゴリを一巡させることが観点の網羅につながるという発想が出発点です。
正常系と異常系・エラー系
正常系は「仕様どおりに使えば正しく動く」ことの確認、異常系は「仕様外の入力にどう振る舞うか」の確認です。実務で漏れやすいのは後者で、必須欠落・型違反・不正フォーマットなどをわざと送り、想定どおりのエラーが返るかを見ます。
| カテゴリ | 確認する内容 | 代表例 |
|---|---|---|
| ①正常系 | 期待どおりの成功応答 | 有効なIDで200とデータが返る |
| ②異常系・エラー系 | 不正入力への適切なエラー | 必須項目欠落で400または422が返る |
| ③バリデーション・境界値 | 値の判定ロジック | 文字数上限+1で拒否される |
| ④認証・認可 | アクセス制御 | 他人のリソースに403 |
| ⑤ステータス/レスポンス | コードとボディの整合 | 作成成功で201とLocation |
| ⑥冪等性・副作用 | 再送時の安全性 | 同じPUTを2回でも状態が同じ |
| ⑦パフォーマンス・レート制限 | 負荷・制限時の挙動 | 制限超過で429 |
バリデーション・境界値と認証・認可
③〜④は「攻撃者や不注意なクライアント」を想定する観点です。境界値や無効同値クラスを意図的に送る、他人のIDを差し替えて越境を試す、といった能動的な確認がここに含まれます。
冪等性・副作用とパフォーマンス
冪等(べきとう)とは、同じリクエストを何度送ってもサーバの最終状態が同じになる性質です。レスポンスまで毎回同じとは限りません。たとえばDELETEは2回目が404でも、リソースが消えているという最終状態は変わらないため冪等です。
HTTPメソッドは次のように整理できます。GETは安全(副作用なし)、PUTとDELETEは冪等、POSTとPATCHは非冪等(PATCHは冪等が保証されない)。二重送信時の副作用は、とくにPOST・PATCHで重点確認ポイントになります。
ステータスコードとレスポンスの検証観点
期待コードは仕様に固定する
ステータスコードは、サーバーが「リクエストをどう処理したか」を表す最初のシグナルです。ここで最も大切なのは、期待するコードの決め方です。
期待コードは必ずそのAPIの仕様/OpenAPI定義に固定し、RFCの一般則は仕様が無い・曖昧なときの当たり判定に使うのが原則です。RFCの「あるべき値」を断定の根拠にすると、仕様と食い違ったときに正しいバグ報告ができません。
2xx・4xx・5xxの意味と400・422の使い分け
まず各コード帯の意味を押さえます。
- 2xx(成功): 処理が成功した。取得なら200、作成なら201、本文なしなら204
- 4xx(クライアントエラー): リクエスト側に問題がある。不正な入力・未認証・権限不足など
- 5xx(サーバーエラー): サーバー側で処理に失敗した。想定外の例外など
入力不正のうち、400は構文・形式そのものが不正でパースできない場合、422は構文は正しいが意味的に処理できない(バリデーション違反)場合に使い分けられます。どちらを採用しているかは仕様で確認し、期待値を1つに固定してください。クライアント起因のエラーを5xxで返す実装はバグのサインです。
500と503・リトライ挙動
5xxは一括りにせず分けて見ます。500は想定外の例外で、原則クライアント側では回復できません。一方503は一時的な利用不可(過負荷やメンテナンス)で回復可能なため、Retry-Afterヘッダの有無と、クライアントが適切に再試行するかまで確認します。500と503を混同した実装は、リトライ設計を誤らせます。
レスポンスボディとヘッダの検証
ステータスコードだけでなく、レスポンスの中身も検証します。確認するのは主にボディ(スキーマ・必須項目・値・エラーメッセージ形式)、ヘッダ、両者の整合性です。
ステータスには対で検証すべき代表ヘッダがあります。201はLocation、401はWWW-Authenticate、429はRetry-Afterを併せて確認してください。各コードの正確な意味は独自解釈せず、MDNのHTTPステータスコード一覧で定義を確認します。テストレベルなどの用語定義はJSTQBの公式サイトも参考になります。
| コード帯 | 代表コード | 想定シーン | 確認ポイント |
|---|---|---|---|
| 2xx | 200 / 201 / 204 | 取得・作成・削除の成功 | 仕様で定義された成功コードで返るか(201はLocationも) |
| 4xx | 400 / 422 | 構文不正・意味的な検証エラー | 仕様の使い分けに一致するか |
| 4xx | 401 / 403 / 404 / 409 / 429 | 未認証・権限不足・不存在・競合・制限超過 | 原因に応じ正しく返し分けるか |
| 5xx | 500 | サーバー例外 | クライアント起因の誤りを5xxにしていないか |
| 5xx | 503 | 一時停止・過負荷 | 回復可能でRetry-Afterを返すか |
バリデーション・境界値をAPIパラメータに適用する
同値分割でパラメータを分類する
画面のバリデーションを信じてはいけません。APIは直接叩けるため、入力チェックはサーバー側でも検証する必要があります。ここで役立つのが同値分割と境界値分析です。
Copeland『はじめて学ぶソフトウェアのテスト技法』は同値クラスを「モジュールが同等に処理するデータの集合」と定義し、要件で想定される値を有効同値クラス、それ以外を無効同値クラスに分けます。「1〜100の数値」なら有効クラス(1〜100)と無効クラス(0以下、101以上、数値以外)に分け、各クラスの代表値をリクエストに乗せます。
境界値をリクエストに適用する
境界値については、同書は「境界にはたくさんの欠陥が潜んでいる」と述べ、境界値±1の確認を勧めます。APIパラメータで確認したい境界・違反パターンは次のとおりです。
- 数値範囲: 下限・下限−1、上限・上限+1、0、負数
- 文字列長: 最小長・最小長−1、最大長・最大長+1、空文字
- 日付: 有効な最古/最新日、範囲外、存在しない日付(例: 2月30日)
- 型違反: 数値に文字列、真偽値に数値など
- 必須違反: 必須項目の欠落、null、空
- フォーマット違反: メールアドレスやIDの形式崩れ
画面で入力できない値こそ、APIには直接送れてしまうため、境界と違反パターンを意図的に投げて確認することが重要です。
ページネーション・ソート・フィルタの境界
一覧系エンドポイントは境界の宝庫です。次を必ず確認します。
- ページ番号:
page=0、負数、総件数を超える巨大値でどう振る舞うか - 件数整合: 各ページの合計と総件数(total)が一致するか
- 不正なソートキー: 定義外のキーやSQL断片を渡して安全に拒否されるか
各技法の手順は、境界値分析のやり方を見ると同値分割法の手順を見るで詳しく確認できます。
認証・認可のテストとテストデータの準備
認証のテスト
認証と認可は混同されがちですが、テスト観点としては明確に分けます。認証は「あなたは誰か」を確かめる仕組みです。
認証は”誰か”、認可は”何を許すか”を分けて確認すると、観点の抜けが減ります。認証で試すべきパターンは、トークン欠落(401)、期限切れトークン、署名や中身を書き換えた改ざんトークン、でたらめな不正値の拒否です。
認可のテスト(越境の403/404判定軸)
認可(Authorization)では、権限別アクセス制御(一般ユーザーが管理者用エンドポイントで403か)、越境アクセス(他人のリソースIDを指定して取得・更新できないか)、権限昇格(ボディでロールを書き換えても無視されるか)を試します。
越境時のコードには判定軸があります。情報漏洩防止で存在自体を隠す場合は404、明示的に拒否する場合は403を返します。どちらであっても「他人のデータが返らないこと」が合格条件です。IDを差し替えたリクエストは必ず投げて確認します。
トークンと前提データの準備
認証・認可のテストは、データの準備で品質が決まります。
- トークンの取得: ログインAPIでアクセストークンを取得し、環境変数に保存して各リクエストで使い回す
- 期限切れ・改ざんの作り方: 期限切れは短命トークンを発行して待つか過去日時のものを用意し、改ざんは署名部を1文字書き換えて用意する
- 前提データ: テスト用ユーザーを2人(AとB)用意し、事前に1件POSTしておくと、越境(Aのトークンで Bのリソース)を確実に再現できる
認証・認可はセキュリティの入口でもあります。攻撃者視点の観点は、セキュリティテストの基本を確認するとあわせて押さえておくと安心です。
OpenAPI定義から観点を起こしスキーマ検証する
定義のどこを見るか
OpenAPI定義がある場合、テスト観点は感覚ではなく定義から機械的に起こせます。OpenAPI定義は「あるべき仕様」の一次情報であり、テスト観点も期待ステータスもここから導けるため、まずこのファイルを読み解きます。
定義項目と観点カテゴリの対応表
定義の各項目は、これまで挙げた観点カテゴリと素直に対応します。
| 定義項目 | 見る場所 | 対応する観点カテゴリ |
|---|---|---|
| エンドポイント一覧 | paths | テスト対象の洗い出し |
| パラメータ・リクエストボディ | parameters / requestBody(required・type・format) | バリデーション・境界値 |
| レスポンス定義 | responses(ステータスとスキーマ) | ステータスコード・レスポンス検証 |
| 認証方式 | security / securitySchemes | 認証・認可 |
requiredとtype、formatを見れば必須違反・型違反・フォーマット違反のケースが、responsesを見れば固定すべき期待ステータスが、そのまま導けます。
スキーマ検証・契約テスト
レスポンスは、OpenAPIやJSON Schemaと突き合わせて構造レベルで検証します。項目の増減・型の変化・必須の欠落を「契約からの逸脱」として捉えれば、気づきにくい退行(デグレ)を自動で検出できます。期待値を仕様に固定するという前章の原則が、ここで契約テストとして具体化します。
APIテストのやり方を実演する(curl・Postman)
題材として、ユーザー登録 POST /users と取得 GET /users/{id} の2エンドポイント(ドメインは例示の api.example.com)を使って手を動かします。
curlで送る実リクエスト例
まず正常系。作成成功は201とLocationを確認します。
`
curl -i -X POST https://api.example.com/v1/users \
-H “Authorization: Bearer $TOKEN” \
-H “Content-Type: application/json” \
-d ‘{“name”:”Taro”,”email”:”taro@example.com”}’
# 期待: HTTP/1.1 201 Created
# Location: /v1/users/1001
# {“id”:1001,”name”:”Taro”,”email”:”taro@example.com”}
`
必須欠落の異常系(仕様が422を採用している場合)。
`
curl -i -X POST https://api.example.com/v1/users \
-H “Authorization: Bearer $TOKEN” \
-H “Content-Type: application/json” \
-d ‘{“name”:”Taro”}’
# 期待: HTTP/1.1 422 Unprocessable Entity
# {“errors”:[{“field”:”email”,”message”:”required”}]}
`
トークン欠落は401とWWW-Authenticateを確認します。
`
curl -i -X POST https://api.example.com/v1/users \
-H “Content-Type: application/json” \
-d ‘{“name”:”Taro”,”email”:”taro@example.com”}’
# 期待: HTTP/1.1 401 Unauthorized
# WWW-Authenticate: Bearer
`
越境アクセス(ユーザーAのトークンでBのリソースを取得)。
`
curl -i https://api.example.com/v1/users/2002 \
-H “Authorization: Bearer $TOKEN_USER_A”
# 2002 はユーザーBのリソース
# 期待: 403 または 404(仕様に固定)/他人のデータが返らないこと
`
1本のcurlで送れてしまう異常系こそ、画面では再現できないAPIならではの検証対象です。
Postmanでアサーションを書く
目視をアサーションに変えると再現性が上がります。ステータス、プロパティと型、JSONスキーマ、トークン保存の4スニペットを押さえます。
`
// ステータス検証
pm.test(“status is 201”, function () {
pm.response.to.have.status(201);
});
// ボディのプロパティ・型検証 pm.test(“body has id and email”, function () { const body = pm.response.json(); pm.expect(body).to.have.property(“id”); pm.expect(body.email).to.be.a(“string”); });
// JSONスキーマ検証 const schema = { type: “object”, required: [“id”, “name”, “email”], properties: { id: { type: “integer” }, name: { type: “string” }, email: { type: “string” } } }; pm.test(“schema is valid”, function () { pm.response.to.have.jsonSchema(schema); });
// ログインAPIのレスポンスからトークンを環境変数に保存
const token = pm.response.json().access_token;
pm.environment.set(“TOKEN”, token);
`
着手の優先順位
限られた時間では、壊れたときの被害が大きいものから着手します。
- 更新系(POST/PUT/PATCH/DELETE)を参照系より先に
- 課金・決済に関わるエンドポイント
- 認証必須のエンドポイント
- メール送信・在庫引き当てなど副作用のある処理
そのまま使えるAPIテストのやり方チェックリスト
4区分チェックリスト
ここまでの観点を、コピペして流用できるチェックリストにまとめます。期待結果は「あるべき値」ではなく、そのAPIの仕様で定義されたコードに固定してから使ってください。
| 区分 | 確認項目 | 期待結果の例(仕様に固定する) |
|---|---|---|
| 正常系 | 有効な入力で成功する | 仕様で定義された成功コード(多くは200/201)とボディ |
| 正常系 | レスポンスのスキーマ・必須項目 | 定義どおりの構造と型で返る |
| 正常系 | 作成・更新・削除が反映される | 後続の取得で状態が一致 |
| 異常系 | 必須項目の欠落 | 仕様が定めるコード(400または422)でエラー内容が返る |
| 異常系 | 型・フォーマット違反 | 仕様どおりの4xxで拒否される |
| 異常系 | 存在しないリソース | 仕様で定義されたコード(多くは404) |
| 異常系 | 競合・重複登録 | 仕様が定めるコード(409など)で返る |
| 境界 | 数値・文字列長の上限下限±1 | 境界内は成功、境界外は仕様どおり拒否 |
| 境界 | 空文字・null・0・負数 | 仕様どおりに受理/拒否される |
| 認証 | トークン欠落・期限切れ・改ざん | 401で拒否される |
| 認可 | 権限外エンドポイントへのアクセス | 403で拒否される |
| 認可 | 他人のリソースへの越境アクセス | 仕様に応じ403または404で遮断 |
自案件の観点表へ落とす
チェックリストは埋めるための儀式ではなく、自案件の観点表へ翻訳する下地として使うものです。エンドポイントの一覧を縦軸、この区分を横軸にした表を作ると、抜けが一目で見えます。
観点を洗い出す手順そのものを固めたい場合は、テスト観点の洗い出し手順を見るが役立ちます。
手動から自動化・CI組み込みへ
手動の進め方
最初から自動化を目指す必要はありません。まずPostmanなどで手動確認を固め、段階的に自動化・CI組み込みへ発展させるのが現実的なAPIテストのやり方です。手動フェーズでは、リクエストをコレクションに整理し、ベースURLやトークンを環境変数化し、目視を少しずつアサーションへ移すと迷いません。
モックで外部依存を切り離す
自動化で避けて通れないのが外部依存の切り離しです。Khorikov『単体テストの考え方/使い方』は、管理下にない依存(外部APIなど)はモック化し、管理下にある依存(自前のDBなど)は実物を使う、と使い分けを示します。フロントエンド側からWeb APIをモックする手法としては、吉井健文『フロントエンド開発テスト入門』が紹介するMSW(Mock Service Worker)があり、ネットワークレベルでレスポンスを差し替えられます。
CI組み込みの注意と二重送信・冪等性キー
CI組み込みでは目的と役割を見誤らないことが肝心です。林尚平『ソフトウェアテスト自動化の教科書』は自動テストの目的はコスト削減と効率化であり、役割はデグレ確認であると述べます。同書は自動テストを5回以上実行しないと作成工数を取り返せない趣旨も指摘しており、繰り返し流して初めて元が取れます。CIで毎回流すなら、実行のたびに結果が揺れる不安定な(Flakyな)テストは避けます。
非冪等なPOST・PATCHでは、二重送信対策も観点に含めます。ネットワークのタイムアウトで再送された際、処理が二重実行されないかを確認します。決済や在庫では致命的になるため、Idempotency-Keyのようなキーで重複実行を防ぐ設計になっているかを検証します。
| 段階 | やること | 使うもの | 得られる効果 |
|---|---|---|---|
| 手動確認 | リクエストを整理し目視確認 | Postman等・環境変数 | 観点の洗い出しと再現性 |
| 半自動 | 期待値をアサーション化 | ツールのテスト機能 | 確認の再現性・省力化 |
| 自動化 | 外部依存を切り離し繰り返し実行 | モック・スタブ | 安定した反復実行 |
| CI組み込み | プッシュ毎にデグレ確認 | CIパイプライン | 退行の早期検出 |
不具合出しは発想力を要する人間の領域、自動化はデグレ確認の領域、と役割を分けるのがバランスの取れた進め方です。自動化の全体像はWebアプリのテスト自動化を見るでも整理しています。
よくある質問(FAQ)
Q. APIテストと結合テストは同じものですか。
厳密には別の切り口です。結合テストはテストレベル(どの範囲を結合して確認するか)の概念で、APIテストはテスト対象(APIのリクエスト/レスポンス)の概念です。APIを対象に結合レベルで検証する重なりはありますが、イコールではありません。
Q. APIテストはどこまで自動化すべきですか。
繰り返し実行してデグレを確認したい部分から自動化するのが基本です。目的はコスト削減、役割はデグレ確認と割り切り、実行回数が少ないものや発想力を要する意地悪な確認は手動で残すとバランスが取れます。
Q. 画面がない分、バグを見逃していないか不安です。
不安は観点で潰します。正常系だけでなく、異常系・境界値・認証認可の各カテゴリを一巡させ、チェックリストで抜けを可視化すれば、見逃しは着実に減ります。画面で防いでいる値こそ、APIに直接投げて確かめてください。
Q. APIテストに必要なツールは何ですか。
最初はcurlとPostmanで十分です。curlで単発のリクエストを送って挙動を確かめ、Postmanでコレクション化してアサーションを書けば、手動確認から半自動まで一通りカバーできます。OpenAPI定義があれば、スキーマ検証や契約テストにも発展させられます。
Q. GraphQLでも同じ観点でよいですか。
正常系・異常系・バリデーション・認証認可・冪等性といった観点カテゴリはそのまま流用できます。ただしGraphQLは基本的に単一エンドポイントで、エラーがHTTPステータスではなくレスポンスボディのerrorsフィールドで表現されることが多い点が異なります。ステータスコード検証の比重を、ボディ内のエラー構造の検証に置き換えて考えます。
Q. レスポンスタイム(性能)はどこまで見ますか。
機能検証の段階では、明らかに遅い異常を拾える程度で十分です。本格的な性能・負荷の測定は、専用のツールと十分な準備のもとで別途行う領域です。まずは機能・観点の網羅を固め、性能は要件が定まってから個別に計画するのが現実的です。
テストに関するノウハウ資料を公開しています。実務で使える観点や進め方をさらに深めたい方は、テスト実務のノウハウ資料を見るをご覧ください。
次に読むならこの記事
テストの手戻りを減らしたい方へ
テスト仕様書のExcelテンプレートを無料で配布しています。自社で整備する場合も、外部に任せる場合も、まずは型を持つところから。



