OpenAPI によるバックエンド API の設計とテスト
Grace Collins
Solutions Engineer · Leapcell

はじめに
ソフトウェア開発が急速に進化する中で、API は現代のアプリケーションの基盤となり、異なるシステム間のシームレスな通信を促進しています。これらのアプリケーションが複雑化するにつれて、API の一貫性、ドキュメント、テストの管理は重大な課題となります。従来の アプローチでは、ドキュメントの不一致、煩雑な手動テスト、フロントエンドとバックエンド チーム間のコミュニケーションの断絶につながることが often あります。ここで、OpenAPI 仕様(Swagger とも呼ばれる)がゲームチェンジャーとして登場します。OpenAPI は、 nación REST API のための普遍的で言語に依存しないインターフェイス記述を提供することで、開発者が前例のない明確さと効率性で API を定義、設計、使用できるようにします。この記事では、OpenAPI がバックエンド API の設計とテスト プロセスをどのように推進し、それを受動的な雑務から開発ライフサイクルの能動的で不可欠な、一部に変えるかを探ります。
コアコンセプトの理解
実践に入る前に、OpenAPI に関連する主要な terms を共通理解しましょう。
- API(Application Programming Interface): 異なるアプリケーションが互いに通信できるようにする定義済みのルールセット。バックエンドの目的では、通常 HTTP メソッドを使用するネットワーク アプリケーションのアーキテクチャ制約に従う RESTful API を主に focus します。
- OpenAPI 仕様(OAS): RESTful API のための標準化された言語に依存しないインターフェイス記述。ソースコードや追加のドキュメントにアクセスすることなく、人間とコンピューターの両方がサービスの機能を discover し、理解できるようにします。YAML または JSON 形式で記述されることが often あります。
- Swagger: 歴史的には、Swagger は OpenAPI 仕様を中心に構築されたオープンソースツールセットを指しました。これには、Swagger UI(インタラクティブな API ドキュメント用)、Swagger Editor(API 設計用)、Swagger Codegen(サーバー スタブおよびクライアント SDK の生成用)が含まれます。「Swagger」という言葉は仕様自体を指すために common に使用されますが、仕様は Linux Foundation に寄贈され、「OpenAPI 仕様」に改名されました。
- API ファースト設計: 実装 前 に API を設計および指定するアプローチ。これはコード ファーストまたはデータベース ファーストのアプローチとは対照的であり、contract 駆動型開発プロセスを奨励します。
- サーバー スタブ: OpenAPI 仕様から生成された基本的なサーバーサイド実装。API エンドポイントの boilerplate コードを提供し、実際のビジネスロジックを挿入できます。
- クライアント SDK(Software Development Kit): OpenAPI 仕様から生成されたコードのライブラリ。クライアント(例:フロントエンド アプリケーション)が HTTP リクエストの詳細を抽象化して、API と簡単にやり取りできるようにします。
OpenAPI による設計の推進
API 設計に OpenAPI を使用する基本的な原則は API ファースト開発 です。コードを記述してからドキュメント化するのではなく、まず OpenAPI 仕様を使用して API 契約を定義します。
原則:API ファースト開発
API ファースト アプローチでは、OpenAPI ドキュメントが単一の真実の源となります。チームはこの仕様について collaboration し、以下を定義します。
- エンドポイントとパス: 異なるリソースにアクセスするための URL(例:
/users、/products/{id})。 - HTTP メソッド: これらのリソースに対して実行できるアクション(例:
GET、POST、PUT、DELETE)。 - リクエスト/レスポンス スキーマ: API に送信されるデータと API から受信されるデータの構造とデータ型。JSON Schema を使用して定義されることが often あります。
- パラメーター: 各操作に必要な入力(パス、クエリ、ヘッダー、Cookie)。
- 認証と承認: 使用されるセキュリティ スキーム(例:API キー、OAuth2)。
- エラー レスポンス: さまざまなシナリオに対する標準化されたエラー形式。
実装:Swagger Editor による設計
Swagger Editor のようなツールを使用すると、開発者は OpenAPI 仕様をインタラクティブに記述できます。リアルタイム検証と生成されたドキュメントのプレビューを提供します。
例:シンプルなユーザー API
ユーザーを管理するための基本的な API を設計しましょう。
# user-api.yaml openapi: 3.0.0 info: title: User Management API version: 1.0.0 description: API for managing user accounts. servers: - url: http://localhost:8080/api/v1 description: Local Development Server paths: /users: get: summary: Retrieve a list of users operationId: listUsers parameters: - name: limit in: query description: How many items to return at one time (max 100) required: false schema: type: integer format: int32 responses: '200': description: A paged array of users content: application/json: schema: type: array items: $ref: '#/components/schemas/User' default: description: unexpected error content: application/json: schema: $ref: '#/components/schemas/Error' post: summary: Create a new user operationId: createUser requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserCreationRequest' responses: '201': description: User created successfully content: application/json: schema: $ref: '#/components/schemas/User' default: description: unexpected error content: application/json: schema: $ref: '#/components/schemas/Error' /users/{userId}: get: summary: Info for a specific user operationId: showUserById parameters: - name: userId in: path required: true description: The ID of the user to retrieve schema: type: string responses: '200': description: Expected response to a valid request content: application/json: schema: $ref: '#/components/schemas/User' '404': description: User not found content: application/json: schema: $ref: '#/components/schemas/Error' default: description: unexpected error content: application/json: schema: $ref: '#/components/schemas/Error' components: schemas: User: type: object required: - id - name properties: id: type: string format: uuid example: d290f1ee-6c54-4b01-90e6-d701748f0851 name: type: string example: Alice email: type: string format: email example: alice@example.com UserCreationRequest: type: object required: - name - email properties: name: type: string example: Bob email: type: string format: email example: bob@example.com Error: type: object required: - code - message properties: code: type: integer format: int32 message: type: string
この YAML ファイルは、ユーザー API を正確に定義しています。フロントエンド開発者は、送信すべきリクエストと期待すべきレスポンスを正確に知ることで、この契約に対してすぐに UI の構築を開始できます。バックエンド開発者は、この仕様を使用して実装を推進できます。
アプリケーション:コード生成
OpenAPI 仕様が finalized したら、Swagger Codegen のようなツールを使用してサーバー スタブとクライアント SDK を生成できます。
- バックエンド(サーバー スタブ生成): Spring Boot、Node.js(Express)、または Flask のようなバックエンド フレームワークの場合、Codegen はコントローラー インターフェイス、モデル クラス、さらには基本的なルーティングを生成できます。開発者は、生成された構造内のビジネスロジックを埋めます。これにより、実装が定義された API 契約に厳密に従うことが保証されます。
# Example using openapi-generator-cli for a Spring Boot server stub npx @openapitools/openapi-generator-cli generate \ -i user-api.yaml \ -g spring \ -o ./generated-server \ --additional-properties packageName=com.example.userapi ``` このコマンドは、実装の準備ができた `UserController` インターフェイス、`User` モデル クラスなどを含む Spring Boot プロジェクトを生成します。 * **フロントエンド(クライアント SDK 生成):** React、Angular、またはモバイル アプリのようなフロントエンド フレームワークの場合、Codegen は API 呼び出しをカプセル化するクライアントサイド ライブラリを生成できます。これにより、手動での HTTP リクエストの構築と解析が不要になり、エラーが削減され、開発時間が節約されます。 ```bash # Example using openapi-generator-cli for a TypeScript client npx @openapitools/openapi-generator-cli generate \ -i user-api.yaml \ -g typescript-axios \ -o ./generated-client ``` これにより、フロントエンド開発者がインポートして使用できる TypeScript クライアントが生成されます:`api.user.listUsers({limit: 10})`。 ## OpenAPI によるテストの推進 OpenAPI 仕様は、ドキュメントと設計のためだけのものではありません。API テストの自動化のための強力な資産です。 ### 原則:契約テストと自動検証 OpenAPI ドキュメントはテスト オラクルとして機能します。API 実装はすべて、この契約に準拠する必要があります。これにより、以下が可能になります。 1. **スキーマ検証:** リクエスト ボディとレスポンス ボディが定義された JSON スキーマに準拠していることを確認します。 2. **エンドポイント カバレッジ:** 定義されたすべてのエンドポイントが正しく応答することを検証します。 3. **動作テスト:** 仕様に基づき、有効な入力、エッジ ケース、エラー条件を含むさまざまなシナリオをカバーするテスト ケースを作成します。 ### 実装:専用ツールによるテスト OpenAPI を自動テストに利用するツールがいくつかあります。 * **Postman/Insomnia:** これらの人気のある API クライアントは、OpenAPI 仕様をインポートしてリクエスト コレクションを生成できます。これにより、手動および自動テストがはるかに容易になります。その後、スキーマに対するレスポンスを検証するため、アサーションを追加できます。 * **Dredd (Node.js 用) / Schemathesis (Python 用):** これらのツールは、OpenAPI 仕様を直接読み取り、API 実装をそれに対してテストします。スキーマ定義に基づいてテスト ケースを自動生成し、レスポンスを検証できます。 **例:Schemathesis によるテスト(Python バックエンド)** ユーザー API が Flask を使用して Python で実装されていると仮定しましょう。 ```python # app.py (minimal Flask app example) from flask import Flask, jsonify, request import uuid app = Flask(__name__) users_db = {} # In-memory store @app.route('/api/v1/users', methods=['GET']) def list_users(): limit = request.args.get('limit', type=int, default=100) return jsonify(list(users_db.values())[:limit]) @app.route('/api/v1/users', methods=['POST']) def create_user(): data = request.json if not data or 'name' not in data or 'email' not in data: return jsonify({"code": 400, "message": "Missing name or email"}), 400 new_user = { "id": str(uuid.uuid4()), "name": data['name'], "email": data['email'] } users_db[new_user['id']] = new_user return jsonify(new_user), 201 @app.route('/api/v1/users/<user_id>', methods=['GET']) def show_user_by_id(user_id): user = users_db.get(user_id) if user: return jsonify(user), 200 return jsonify({"code": 404, "message": "User not found"}), 404 if __name__ == '__main__': app.run(debug=True, port=8080) ``` `schemathesis` を使用してこの Flask アプリケーションをテストするには: ```bash # Firstly, install schemathesis pip install schemathesis flask gunicorn # Save your flask app as app.py and run it gunicorn -b 127.0.0.1:8080 app:app & # Then run schemathesis against your running API and the OpenAPI spec schemathesis run -H "Accept: application/json" --base-url="http://127.0.0.1:8080/api/v1" user-api.yaml ``` `schemathesis` は、スキーマ違反、未処理のエラー、その他の API の一貫性のない検出を試みる数千のリクエストを送信します。`user-api.yaml` に定義されたスキーマと形式に従って API に負荷をかけるために、多様な入力値を自動生成します。 * **特定のフレームワーク統合:** 多くのバックエンド フレームワークは統合を提供しています。たとえば、Spring Boot では `springdoc-openapi` がアノテーションから `openapi.json` を生成でき、その後 REST Assured のようなツールでスキーマ検証を使用できます。あるいは、コード生成をサポートするフレームワークの場合、生成された DTO は単体テストおよび統合テストで直接使用でき、型安全性とシリアライゼーションの準拠性を保証します。 ### アプリケーション:継続的インテグレーションとデリバリー(CI/CD) OpenAPI を活用したテストを CI/CD パイプラインに統合することで、すべてのコード変更が API 契約に対して検証されることが保証されます。 * **コミット前フック/プッシュ前フック:** OpenAPI 仕様自体の構文の正確性とベスト プラクティスを検証します。 * **ビルド パイプライン:** クライアント SDK とサーバー スタブを自動生成します。デプロイされた API(またはモック)に対して、自動契約テスト(`schemathesis`、Dredd)を実行します。 * **デプロイメントゲート:** 契約テストが失敗した場合、ビルドを失敗させ、非準拠 API のデプロイを防ぎます。 この堅牢なテスト手法は、壊れる可能性のある変更を早期に検出、一貫性を強制し、API のコンシューマーの統合問題のリスクを大幅に削減します。 ## 結論 OpenAPI 仕様は、API 開発をアドホックなタスクのシリーズから構造化された contract 駆動型プロセスへと変革します。設計を推進するために活用することで、単一の真実の源を確立し、コード生成による並列開発、合理化されたコミュニケーション、迅速なプロトタイピングを可能にします。さらに、テストフェーズに OpenAPI を統合することで、開発者は contract 検証と網羅的な動作テストを自動化し、API の品質と定義された標準への準拠を保証できます。OpenAPI ファースト アプローチを採用することで、API ライフサイクル全体での collaboration、効率性、信頼性が大幅に向上します。本質的に、OpenAPI は設計と実装の間のギャップを埋め、開発者が自信を持って堅牢で保守可能で、文書化された API を構築できるようにします。

