💡 Key Takeaways
- Authentication and Authorization: The Foundation Layer
- Request Validation: Input Boundary Testing
- Response Validation: Ensuring Data Integrity
- Error Handling: The Difference Between Good and Great APIs
3年前、午前2時にプロダクションAPIが壮絶に失敗するのを見ました。誰も「32/13/2021」というフォーマットの日付フィールドを送信したときに何が起こるかをテストしなかったからです。カスケードは最悪の方法で美しかった:47,000件の失敗したトランザクション、怒った顧客がサポートチャネルに殺到し、私が持っていない回答を求めるCEO。その夜、APIテストへのアプローチが永遠に変わりました。
💡 重要なポイント
- 認証と認可:基盤レイヤー
- リクエストバリデーション:入力境界テスト
- レスポンスバリデーション:データの整合性を確保
- エラーハンドリング:良いAPIと優れたAPIの違い
私はサラ・チェンです。QA自動化エンジニアとして8年の経験があり、過去5年はフィンテックとヘルスケアプラットフォームのAPIテストに専念しています。単純なCRUDエンドポイントから、毎日何百万ドルを処理する複雑な決済処理APIまで、すべてをテストしてきました。私が学んだことは、ほとんどのAPIの失敗はエキゾチックなエッジケースではなく、体系的なチェックリストでキャッチできる予測可能な問題であるということです。
今日共有するチェックリストは、私がテストするすべてのエンドポイントに対して使用する正確なものです。これは、過去1年間に少なくとも12件のプロダクションインシデントから私たちのチームを救ってきましたし、ジュニアエンジニアが追従できるほど包括的であり、シニア開発者が見逃す問題をキャッチするほど詳細です。これは理論ではなく、数百のAPI実装を通じて洗練された実践済みプロセスです。
認証と認可:基盤レイヤー
他の何かをテストする前に、セキュリティの周辺を確認します。これは単に認証が機能するかどうかを確認するだけではありません—すべての認証シナリオと認可の境界を系統的に調査することです。有効な資格情報では完璧に動作するが、資格情報が不足している、誤った形式である、あるいは間違ったユーザーのものであるときに、壊滅的に失敗したりデータが漏れたりするAPIを見てきました。
まず、認証トークンなしでテストします。エンドポイントは401 Unauthorizedのステータスを返すべきであり、500 Internal Server Errorを返したり、実際のデータを返したりしてはいけません。私は、開発者が認証ミドルウェアが常に実行されると仮定したために、認証トークンが提供されなかったときに完全なユーザーレコードを返したプロダクションAPIに遭遇したことがあります。そうではありませんでした。
次に、期限切れのトークンでテストします。これは意外な数の問題をキャッチします。なぜなら、トークンの有効期限ロジックが初期認証とは異なるコードベースの部分にあることが多いからです。レスポンスは明確な401で、トークンが期限切れであることを示すメッセージが必要です。一般的な「unauthorized」ではなく、クライアントがリフレッシュするか再認証するかを予測させるメッセージです。
次に、無効なトークンでテストします—ランダムな文字列、文字が削除されたトークン、他のシステムからのトークン。APIはこれらを優雅に処理し、スタックトレースや内部エラーの詳細を公開しないべきです。かつて、特定のUnicode文字を含むトークンが与えられた場合にサービス全体がクラッシュするAPIを見つけたことがあります。それはJWT解析ライブラリがエンコーディングを適切に処理していなかったからです。
認可テストが興味深いところです。私はアクセスしてはいけないリソースに対して有効なトークンを持つユーザーとしてテストします。GET /users/123エンドポイントの場合、ユーザー456として認証し、123のデータにアクセスしようとします。レスポンスは403 Forbiddenであるべきであり、リソースの存在について情報を漏らす404 Not Foundではなく、データを伴う200では絶対にいけません。
また役割ベースのアクセス制御を体系的にテストします。APIに管理者、マネージャー、ユーザーの役割がある場合、各役割で各エンドポイントをテストします。マトリックススプレッドシートを維持します:行がエンドポイント、列が役割、セルには期待されるステータスコードが含まれます。これにより、プロダクションに到達する前に権限のバグをキャッチし、それがセキュリティ脆弱性になるのを防ぎます。
リクエストバリデーション:入力境界テスト
入力バリデーションは、ほとんどのAPIが真の品質を示すところです。適切に設計されたAPIは、すべての入力フィールドを徹底的に検証し、明確で実行可能なエラーメッセージを返します。適切に設計されていないAPIは、ゴミデータを受け入れるか、神秘的にクラッシュします。
「ほとんどのAPIの失敗はエキゾチックなエッジケースではなく、体系的なチェックリストでキャッチできる予測可能な問題です。」
最初に必須フィールドのテストから始めます。任意の必須フィールドについて、それなしでリクエストを送信します。APIは400 Bad Requestを返すべきで、どのフィールドが不足しているかを明確に特定するメッセージを含めるべきです。「バリデーションエラー」と返し、どれが失敗したのかを明示しないAPIを見たことがあります。そのため、開発者は15のフィールドのうちどれが問題を引き起こしたのかを推測することを強いられます。
次に、データ型のバリデーションをテストします。フィールドが整数を期待する場合、私は文字列、浮動小数点数、ブール値、null、配列、オブジェクトを送信します。それぞれは、「年齢は整数でなければならない」といった明確なメッセージを添えて400を返すべきで、 「無効なリクエスト形式」ではないはずです。かつて、数量について文字列を送信した結果、システムがゼロアイテムの注文を作成し、全体の履行パイプラインが壊れたeコマースAPIをテストしたことがあります。
文字列の長さのバリデーションは重要であり、しばしば見落とされます。空の文字列、単一の文字、最大長の文字列、最大を1文字オーバーした文字列、非常に長い文字列(10,000文字以上)でテストします。適切なバリデーションがされていないフィールドにメガバイトサイズの文字列を送信することで、生産データベースをクラッシュさせたことがあります。
数値フィールドについては、境界値を体系的にテストします:ゼロ、負の数、整数が期待される場合の小数、最大整数値を超える数、InfinityやNaNといった特別な値です。私がテストしたある決済APIは、負の決済金額を受け入れていたため、ユーザーが任意にアカウントにクレジットを付与できる可能性がありました。
日付と時刻のバリデーションは特別な注意を要します。なぜなら、常に問題を引き起こすからです。無効な日付(2月30日、13月)、さまざまなフォーマット(ISO 8601、Unixタイムスタンプ、人が読める文字列)、過去や未来の日付、タイムゾーンのエッジケースでテストします。最初に言及した午前2時のインシデントは、日付バリデーションの失敗です。
enumフィールドについては、有効な値、無効な値、大文字小文字のバリエーション、nullでテストします。APIが「active」と「inactive」をステータス値として受け入れる場合、私は「ACTIVE」、「Active」、「pending」、空文字列、nullを試みます。それぞれは、(大文字小文字を区別しない場合)受け入れられるか、有効なオプションをリストした明確なメッセージで拒否されるべきです。
レスポンスバリデーション:データの整合性を確保
入ってくるものをテストすることは、出ていくものをテストすることと同じくらい重要です。リクエストを完璧に受け入れるが、一貫性がなく、不完全で、誤ってフォーマットされたデータを返すAPIを見てきました。
| テストシナリオ | 期待されるレスポンス | 一般的な誤り | リスクレベル |
|---|---|---|---|
| 認証トークンなし | 401 Unauthorized | 500または実際のデータを返す | 重大 |
| 無効な日付フォーマット | 明確なエラーを伴う400 Bad Request | 「32/13/2021」を受け入れ、クラッシュする | 高 |
| 誤ったユーザー資格情報 | 403 Forbidden | 他のユーザーの情報を漏らす |