green snake
Photo by Pixabay on Pexels.com
目次

FastAPI×OpenAPIの次の一歩:クライアントSDK生成と契約テストで「仕様どおりに動くAPI」を自動で守る


要約(最初に結論)

  • OpenAPI(Swagger UI)を整えた次は、仕様を「読むもの」から「使うもの・守るもの」へ進化させるのが効果的です。
  • クライアントSDK生成は、フロントや他サービスの実装速度と品質を底上げします。型とエンドポイントのズレが減り、仕様変更も追いやすくなります。
  • 契約テスト(contract testing)は、OpenAPIに書いた仕様と実装のズレを自動で検出し、破壊的変更を早めに止められます。
  • この記事では、FastAPI側のOpenAPIを前提に、SDK生成の選択肢、運用パターン、Schemathesis系のテストを中心にした実践例をまとめます。

誰が読んで得をするか

  • 個人開発の方:APIとフロントを1人で作っていて、仕様のズレに毎回悩む。SDK生成で「型が正」の状態にしたい。
  • 小規模チームの方:バックエンドとフロントが分かれ、PRでの仕様確認が大変。契約テストで「壊れる変更」を早めに検知したい。
  • SaaS開発チームの方:外部連携や複数クライアントがあり、互換性事故が怖い。OpenAPIを中心にした開発プロセスを整えたい。

アクセシビリティ評価

  • 冒頭に要点、途中に手順とチェックリスト、末尾にまとめを置いて流れを追いやすくしています。
  • 専門用語は初出で短く説明し、同じ用語を繰り返して迷いを減らしています。
  • コードは短いブロックに分割し、必要最小限の記述に留めています。
  • 目標レベルはAA相当です。

1. OpenAPIを「資産」に変える発想

Swagger UIを整えるだけでも価値がありますが、さらに一歩進むと、OpenAPIは次の2つの役割を持てます。

  • クライアント向けの「型の正解」になる
    例:TypeScriptやPythonのSDKを自動生成し、クライアント実装の手戻りを減らす。
  • 実装を縛る「契約」になる
    例:OpenAPIから自動でテストを組み立て、レスポンス形式やステータスコードの逸脱を検出する。

この2つを回し始めると、APIの変更が怖くなくなっていきます。特に、仕様と実装のズレは小さいうちに潰すほど安く済みます。


2. SDK生成の全体像:何を作るのか、どう配るのか

SDK生成は「生成すること」より「配り方」と「更新の流れ」が重要です。

2.1 代表的な生成ターゲット

  • TypeScript(フロント、Node)
  • Python(バッチ、別サービス)
  • Kotlin/Swift(モバイル)
  • Go/Java(社内サービス)

2.2 配布の選択肢

  • Gitリポジトリに生成物をコミット(小規模向け、分かりやすい)
  • パッケージとして配布(npm / PyPI / GitHub Packagesなど)
  • モノレポ内で生成し、同一リポジトリで参照(最もズレが起きにくい)

迷ったら、最初は「SDKを専用ディレクトリに生成し、リポジトリに入れる」でも十分に効果があります。慣れてきたらパッケージ配布へ移行するのが自然です。


3. FastAPI側で先に整えるべきOpenAPIの条件

SDK生成と契約テストを成功させるには、OpenAPIが次の条件を満たしていると安心です。

3.1 レスポンスの型が固定されている

  • response_model を必ず指定
  • 一覧は items + meta のように形を揃える
  • エラーも共通フォーマットに統一(前回の記事で扱った形)

3.2 パラメータの説明と制約が入っている

  • Query(..., ge=0, le=100, description=...)
  • enum値は Literal などで明示

3.3 ステータスコードが意図どおりに出る

  • 作成は 201、削除は 204など
  • 404/422/403などの想定エラーを responses に載せる

この条件が揃うほど、SDK生成の品質が上がり、契約テストのノイズが減ります。


4. SDK生成の実践パターン:TypeScriptを例にする

ここでは「OpenAPI → TypeScriptクライアント」のよくある流れを、まず概念として掴みます。

4.1 生成の入口は openapi.json

FastAPIでは /openapi.json が生成されます。運用では次のどちらかに固定すると安定します。

  • CIで curl して保存する
  • アプリ起動なしで app.openapi() を呼んでJSONを書き出す

後者の例です。

# scripts/export_openapi.py
import json
from app.main import app

def main():
    spec = app.openapi()
    with open("openapi.json", "w", encoding="utf-8") as f:
        json.dump(spec, f, ensure_ascii=False, indent=2)

if __name__ == "__main__":
    main()

この openapi.json を、SDK生成ツールへ渡します。

4.2 生成ツールの考え方(選び方)

生成ツールはたくさんありますが、選定の軸はシンプルです。

  • 生成コードが読みやすいか(レビューできるか)
  • エラー型やレスポンス型が扱いやすいか
  • OpenAPIの一部機能(nullable / oneOfなど)への対応が十分か
  • チームの言語と相性がよいか

小さく始めるなら、まずはTypeScript向けの生成ツールを1つ選び、生成コードの雰囲気が好みかを確認するのが早いです。

4.3 生成されたSDKの使い方サンプル(イメージ)

たとえば「ユーザー一覧API」を叩くクライアントが、型付きで呼べるようになります。

  • 返り値の型が確定している
  • limit の範囲や必須項目が分かる
  • 404や422がどういう形で返るかを、例外型として扱える

これだけで、フロントの実装速度と安心感が上がります。


5. 契約テスト:OpenAPIどおりに動いているかを自動で確かめる

契約テストは、ざっくり言えば「OpenAPIをテストケースの材料にして、APIを叩き、仕様からの逸脱を検出する」仕組みです。

5.1 何が嬉しいか

  • 仕様と実装のズレを機械的に検出できる
  • 破壊的変更をPR段階で止められる
  • 人が読むレビューの負担が減る

5.2 どんなズレが見つかるか(例)

  • OpenAPIに書いてあるのに、実際はフィールドが欠けている
  • status_code=201 のはずが200を返している
  • maxLength を超える文字列が通ってしまう
  • enum外の値が返っている

6. Schemathesisで始める契約テスト(pytest連携の例)

Schemathesisは、OpenAPIからテストを生成してくれる系の代表格です。ここでは概念を掴める最小例を示します。

6.1 インストール(例)

pip install schemathesis pytest

6.2 最小のテスト例(OpenAPI URLを直接参照)

アプリを起動した状態(例:http://localhost:8000)で、OpenAPIを読み、テストします。

# tests/test_contract.py
import schemathesis

schema = schemathesis.from_uri("http://localhost:8000/openapi.json")

@schema.parametrize()
def test_api_contract(case):
    response = case.call()
    case.validate_response(response)

このテストは、OpenAPIに基づいて複数の入力を生成し、レスポンスがスキーマに合っているかを検証します。

6.3 ノイズを減らす実務の工夫

現実のAPIでは、認証や外部依存があり、テストが不安定になりやすいです。最初は次の工夫が効きます。

  • まずは公開系(認証不要)のエンドポイントだけ対象にする
  • tag ごとにテスト対象を絞る
  • 副作用の大きいPOST/DELETEは後回しにする
  • 乱数的な値(日時やUUIDなど)は形式を緩めるか、固定レスポンスにする

たとえばタグで絞るイメージです。

# 概念例(実際のAPIタグ運用に合わせて調整)
# schema = schema.include(tags=["public"])

7. 認証付きAPIを契約テストするパターン

認証がある場合は、テスト側でトークンを付与します。運用としては次の2パターンが分かりやすいです。

7.1 テスト専用ユーザーでトークンを取得して使う

  • テストの最初に /auth/token を叩いてトークン取得
  • 以降のケースに Authorization ヘッダを付与

7.2 テスト環境だけ認証を簡略化する

  • ENV=test のときだけ、固定トークンを許可
  • あるいは依存関数を差し替えて「常にテストユーザー」

最初は 7.2 の方が導入が簡単で、契約テストの効果を早く出しやすいです。慣れてきたら 7.1 に寄せるのが自然です。


8. 仕様変更を安全にする運用:破壊的変更をどう検出するか

SDK生成と契約テストを回し始めると、次に欲しくなるのが「差分検知」です。

8.1 OpenAPI差分をCIで検出する

運用としては、PRで次を自動化すると事故が減ります。

  • openapi.json をエクスポート
  • 既存の openapi.json と差分を比較
  • 破壊的変更(フィールド削除、必須化、型変更など)なら失敗にする

差分ツールはいろいろありますが、ここでは「やるべきこと」を先に決めておくのが大切です。

8.2 非推奨のステップを入れる

  • すぐ削除しない
  • deprecated=True を付ける
  • 移行期間を設ける
  • それでも削除が必要なら /v2へ

この運用ができると、外部連携が増えても怖くなりにくいです。


9. サンプル:よくある改善ポイントをまとめてチェック

SDK生成と契約テストがうまく回りにくい時は、次の点を見直すと改善しやすいです。

  • OpenAPIで response_model が付いていないエンドポイントが多い
  • エラー形式が統一されていない
  • oneOf/anyOf を多用しすぎて、生成側が扱いづらい
  • 例(examples)が不足していて、SDK利用側が迷う
  • 認証や外部API依存で、契約テストが不安定

最初は「公開GETだけ」でも十分に価値があります。完璧を目指さず、対象範囲を少しずつ広げるのが続きやすいです。


10. 参考リンク


まとめ

  • OpenAPIを整えた次は、SDK生成と契約テストで「仕様を使い、仕様で守る」段階へ進めると効果が大きいです。
  • SDK生成はクライアント実装のスピードと品質を上げ、契約テストは仕様と実装のズレを自動で検出します。
  • まずは対象を絞って始めるのがおすすめです。公開GETだけでも、ズレ検出と安心感ははっきり感じられます。
  • 少しずつ対象を広げ、エラー設計・ページネーション・バージョニングをOpenAPIに反映し続けることで、Swagger UIは「読める仕様書」から「開発を支える仕様基盤」へ育っていきます。

投稿者 greeden

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)