20
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AI × FastAPI開発 第1弾】Copilot AgentでAPI実装&単体テストをほぼ自動生成してみた話

20
Last updated at Posted at 2026-01-04

こんにちは!
Dirbatoの社内技術横断支援組織 Backbeat に所属している村石です。

最近、FastAPI 開発のフローに GitHub Copilot Agent を組み込んで運用してみたところ、気づけばチーム内で 「もうCopilotなしでは開発が回らない」 と言われるほどの不可欠な存在になっていました。

この記事は、その運用ノウハウ共有 「第1弾」 です。

サマリー(この記事でわかること)

Copilotを単なる「補助ツール」ではなく、チームの開発フローを回す仕組みとして運用する方法を紹介します。
具体的には、次の3つをサンプル(プロンプト例)つきで解説します。

  1. プロジェクトの 「共通ルール」 をCopilotに教え、前提知識を統一する(.github/copilot-instructions.md
  2. Copilotへの 「指示(プロンプト)」 をテンプレート化し、スラッシュコマンド一つで呼び出せるようにする(.github/prompts/*.prompt.md
  3. 開発フローを工程単位で分解し、各工程にテンプレートを適用することで、作業の属人化を排除する

この運用を導入してから、実装〜テスト〜PR作成までの手順が定型化されたことで、見積もり工数内での完了率が向上しました。

Copilot様、ありがとう〜!!🙏

Copilot神化
(弊社AIツールの画像生成機能でCopilotを神様にしました)

🏃‍♂️ プロジェクト初期の状況

Copilot本格導入前、プロジェクトは以下のような状況でした。

  • スキル差: Python / FastAPIの経験がある人と、ほぼ初めての人が混ざってる
  • タイトな開発スケジュール: とにかく早く開発を進めなければならない
  • 品質のばらつき: コードの書き方・層の切り方が人によって揺れ、レビューに時間が割かれる

とても「各自頑張ってキャッチアップしてね!」と言える状況ではありませんでした。
必要だったのは、 「開発の型を作って、その型に沿えば誰でも同じ品質でアウトプットが出せる」 状態作り。

そこでCopilotを単なる「相談相手」ではなく開発フローに組み込んで、コーディングの大半を任せる方針にしました。

🛠️ 事前準備:プロジェクトの常識をCopilotに教える

copilot-instructions.md でCopilotにルールを共有する

まず、Copilotに「このプロジェクトの常識(ブレてほしくないルール)」を教えます。
やり方は簡単で、リポジトリの .github/ 配下に copilot-instructions.md というファイルを作成し、共通ルールを書いておくだけです。
こうすることで、Copilotは回答生成時に必ずこのファイルを参照するようになります。

これにより、開発者が都度「このプロジェクトでは〜」と説明する手間が省け、誰が聞いても同じ品質のコードが返ってくるようになります。

書き方のコツは、短く・重要なこと(絶対にブレてほしくないルール) のみに絞ることです。
長文の作文調にすると、AIの注目箇所がぼやけて精度が落ちる傾向があります。

copilot-instructions.md のサンプル(例)

※以下はあくまで構成例です。実際のプロジェクトに合わせて調整してください。

<!-- プロジェクトの目的や領域が一目で分かる正式名称を記載する。 -->
# プロジェクト名 - AI コーディングガイド

## AI 応答言語ルール
<!-- Copilotが返答する際の使用言語や文体の統一ルールを記載する。 -->
**IMPORTANT**: AI の返答は常に日本語で行うこと。  

---

## プロジェクト概要
<!-- プロジェクトの目的・開発範囲・使用技術を簡潔に説明する。 -->
- このプロジェクトでは FastAPI(Python)を用いた REST API を開発する。 

---

## アーキテクチャとデータフロー

<!-- プロジェクトの構造とデータの流れを端的にまとめる。-->
### レイヤード構成
- **Router**: API エンドポイント定義、認証 / 認可処理の入口、Service 呼び出し。
- **Service**: ビジネスロジックを集約する層。バリデーション、トランザクション管理、外部サービス連携を担当。
- **DAO**: 永続化を担当する層。DB クエリ、レコードの取得・保存・更新・削除を行う。
- **Schema**: Pydantic モデルによる型定義。入力・出力の構造とバリデーションを管理。

---

## 重要なパターン

<!-- 例外処理・設定管理・認可方針などの設計上の共通ルールを記載する。 -->
### エラーハンドリング
- 業務例外(4xx 系)とシステム例外(5xx 系)を区別して扱う。
- エラー応答は統一フォーマットで返す。  

### 設定管理
- 環境変数または設定ファイル(YAML)で管理する。
- 機密情報は暗号化するか、環境変数から読み込む。  

### 認可
- Router 層で認可判定を行い、失敗時は即座にレスポンスを返す。
- ロールベースのアクセス制御、またはスコープベースの制御を採用する。  

---

## 開発ワークフロー

<!-- 環境構築・テスト・デプロイなど開発工程の手順を記載する。 -->
### ローカルセットアップ
1. 仮想環境の作成・起動
2. データベースサーバの起動
3. FastAPI サーバの起動  

### テスト
- pytest を利用
- 正常系・異常系・境界値のテストケースを網羅
- 外部サービスはモック化してテスト  

### データベースアクセス
- DAO 層を経由し、直接 DB にアクセスしない  

---

## プロジェクト固有の規約
<!-- 命名規則やコード構造などチーム独自のコーディングルールを記載する。 -->
- **命名規則**: snake_case(関数・変数)、PascalCase(クラス名)、英語ベースの意味ある名称。
- **モデル継承**: 共通フィールドはベースモデルにまとめて継承。
- **DAO クエリパターン**: 単機能のメソッド化(find_by_id、list_by_filter など)、N+1 問題の回避。
- **予約語対応**: カラムやフィールド名で予約語を避ける。必要な場合はサフィックスを付与。  

---

## 結合ポイント
<!-- 外部サービスやモジュールとの接続箇所と注意点を記載する。 -->
- 外部サービス: REST API、メッセージキューイングサービスなど
- 認証基盤との接続
- 他モジュールの共通関数やユーティリティの利用  

---

## よくある落とし穴
<!-- 過去の失敗事例や注意すべき実装・運用上のポイントを記載する。 -->
- Router と Schema の型不一致
- 認可漏れ(Router 層で認可処理を忘れる)
- トランザクション管理忘れ(DAO が勝手にコミットする)
- 日付・時間のタイムゾーン統一漏れ
- テスト時に外部サービスとの実接続を避ける設定を忘れる  

書くのが面倒な方向け

VS Codeのコマンドパレットから
> Generate Workspace Instructions File
を実行すると、AIが現在のコードベースを分析してたたき台を作ってくれます(そこから削ったり追加するのが個人的におすすめです)

copilot-instructions.md自動生成

🚀 テンプレートプロンプトによる開発フローの定型化

copilot-instructions.md で共通ルールは整いましたが、開発の進め方(どの順番で作るか)や実装の組み立て方(何から書き、どこまで作るか)には、まだ人によってブレが生じます。

そこで活用したのが、Copilotへの指示をあらかじめファイルとして定義できる テンプレートプロンプト という機能です。

テンプレートプロンプトの機能と呼び出し方法

GitHub Copilot には、定義済みのプロンプトをスラッシュコマンドで呼び出す機能があります。

テンプレートプロンプトを .github/prompts/ 配下に [コマンド名].prompt.md のようなファイル名で配置すると、Copilotのチャット欄で /[コマンド名] と入力するだけで呼び出せるようになります。

利用イメージ

例えば、.github/prompts/test.prompt.md というファイル名のテンプレートプロンプトを作成すると

testプロンプト作成

Copilotのチャット欄で /test と入力して呼び出せます。
(※ Copilotのモードは Agent に設定してください)

testプロンプト呼び出し

あとはEnterを押すだけで、定型化されたプロンプトが実行されます。

testプロンプト実行

実際の開発フロー(STEP 1〜5)

私のプロジェクトでは、この機能を使ってAPI開発を 5つの工程(STEP 1〜5) に分解しました。
各工程に対応するテンプレートプロンプトを用意することで、複雑な指示を毎回入力することなく、担当者が誰であっても均一な品質のアウトプットを得られるようにしています。

5つのステップと、それぞれで使用するテンプレートプロンプトを整理した一覧が以下です。

STEP 手順 使用するテンプレートプロンプト
1 人間向けAPI設計書から、AI実装指示書を作成 実装指示書作成プロンプト
2 Router・Schema(Request/Response)の実装 Router・Schema作成プロンプト
3 ビジネスロジックの実装 ビジネスロジック作成プロンプト
4 pytestによる単体テストコードの作成 単体テスト作成プロンプト
5 各種ドキュメントとプロンプトの更新 ドキュメント更新プロンプト

各STEPの成果物と依存関係を整理した全体フロー図は以下の通りです。
全ての開発メンバーがこのフローに従って作業を進めます。

次に、それぞれのSTEPの詳細を紹介します。


STEP1: 人間向けAPI設計書から、Agent用の「実装指示書」を作らせる

人間向けのAPI設計書をそのままAIに渡すと設計が曖昧な箇所は 雰囲気で実装 されがちです。
しかも、その雰囲気コードはそれっぽく動くため、レビューですり抜けてしまうリスクがあります😱

これを防ぐため、まずCopilotに設計内容を精査させ、
AI自身が実装可能なレベルの指示書 に変換させる工程を設けました。

  • 使用プロンプト: 実装指示書作成プロンプト
  • 入力: 人間向けのAPI設計書
  • 出力: AI向けの実装指示書(Markdown)

実装指示書作成プロンプト(サンプル)

このプロンプトがやっていること:

  1. API設計書を分析して必要情報を抽出
  2. 曖昧・不足している箇所を質問として整理
  3. ユーザー回答で仕様を確定
  4. 完成した仕様をAIが使える形式の指示書にまとめる
# API設計書からAI Agent用実装指示書生成

**目的**  
API設計書から仕様を読み取り、不明点を洗い出して確認し、AIが開発作業を行いやすいよう整理した「実装指示書」を生成する。  
<!-- ここには、このプロンプトが何をするのかを簡潔に記載。AIにとっての最終ゴールを明確化 -->

---

## プロセス

### 1. 入力情報の読取
- HTTPメソッドとエンドポイントパス
- リクエストパラメータ(パス / クエリ / ボディ)
- レスポンス形式(JSON / XML など)
- 処理全体の流れ(概要レベル)
- 制約条件や共通ビジネスルール
- 操作対象となるデータ構造やエンティティ  
<!-- API設計書から最低限抽出すべき項目を列挙 -->

### 2. 既存リソースの確認
- 関連するファイルやモジュール構成を読み取り  
  (例:Router層、Service層、DAO/DataAccess層、Schema定義ファイルなど)  
<!-- 実装の既存状況も参照し、齟齬や再利用ポイントを把握 -->

### 3. 不明点の抽出
- パラメータやレスポンス定義の曖昧さ
- エラーハンドリングやトランザクション境界の未定義箇所
- 検索条件や結合条件の優先順位が不明確
- 外部サービスの利用有無、認証・認可要件の欠落  
<!-- 設計書から曖昧な点や欠落項目を列挙してAIが質問できるようにする -->

### 4. ユーザーへの確認フェーズ
- 抽出した不明点を箇条書きで質問として提示
- 回答を受けて不明点を解消する  
<!-- ユーザーと対話しながら仕様を確定するフェーズを設定 -->

### 5. 実装指示書の生成
- 不明点解消後、以下の条件でMarkdown形式の「実装指示書」を作成
- 全体を4つのバッククォートで囲む  
<!-- 後工程で使う共通フォーマットに従って出力 -->

---

## 出力条件(概要)

### 概要セクション
- APIの目的
- エンドポイント一覧
- 認証の要 / 不要
- 使用するデータ構造や対象エンティティ  
<!-- 仕様の概要を短くまとめる -->

### 処理フロー
- 番号付きで処理手順を列挙
- 各手順に以下を含める:  
  - 処理内容  
  - バリデーション内容  
  - エラーハンドリング方針  
  - トランザクション境界
- コードやSQLの記述は含めない  
<!-- 処理の段階ごとに必要情報を明記し、実装の順序がぶれないようにする -->

### 実装ファイル構成(例)
- Router: エンドポイント定義、認証処理、Service呼び出し
- Service: ビジネスロジック、バリデーション、トランザクション管理
- DataAccess層(DAO等): データ取得・更新処理
- Schema定義: 型定義、バリデーションルール  
<!-- 関係する主要ファイルの役割を提示 -->

### 参考情報(任意)
- 類似機能や共通モジュールへのリンクや説明  
<!-- 再利用可能なコードやパターンを案内 -->

### 注意事項
- プロジェクト共通の実装ルール(命名規則、フォーマットなど)
- 性能要件やセキュリティ上の考慮点  
<!-- 実装時の品質基準を明記 -->

---

## 出力形式
- 指示書全体を4つのバッククォートで囲む
- Markdown形式で構造化して記載  
<!-- 他プロンプトやCopilotに渡しても崩れない形式を保証 -->

このSTEPを入れてから、後続(STEP2〜4)の精度が目に見えて上がりました。
ここで作成した実装指示書を、以降の工程の入力として使います。


STEP2: Router・Schema(Request/Responseモデル)を作る

次にFastAPIの外枠を作って、とりあえずSwaggerで仕様が確認できる状態 にします。

  • 使用プロンプト: Router・Schema作成プロンプト
  • 入力: STEP1の実装指示書
  • 出力: Router / Pydantic Schema

Router・Schema作成プロンプト(サンプル)

このプロンプトがやっていること:

  1. 既存実装を参照して状況把握
  2. Router(エンドポイント)を作成
  3. PydanticのSchema(リクエスト/レスポンスモデル)を作成
  4. Service用スクリプトを用意(中身は未実装で NotImplementedError)
  5. Swagger UIで最低限動作確認できる状態にする
# API エンドポイントのスケルトン生成

**目的**  
APIエンドポイントのスケルトン(Router / Schema)を自動生成し、ビジネスロジック(Service)は未実装(NotImplementedError)のまま Swagger UI で動作確認できる状態を作る。  
<!-- このプロンプトが目指す最終成果物を簡潔に説明する -->

---

## プロセス
<!-- スケルトン生成までの手順を段階的に示す -->

### 1. 指示の受け取り
ユーザーから以下の情報を取得:
- リソース名(例: `post_user``order_item` など)
- 対象となるエンドポイント(HTTPメソッドとパスの組み合わせ)
- 各エンドポイントで扱うフィールド定義(項目名・型・必須/任意)
- 認証/認可の要否(例: ロール制御の有無)  

### 2. 既存実装の確認(任意)
- 既存の Router ファイル、Schema 定義、Service ファイルを確認
- 命名規則や構成を既存プロジェクトと揃える  

### 3. スケルトンの生成
受け取った指示に基づき以下を自動生成(ビジネスロジックは未実装):
- **Router ファイル**:指定の HTTPメソッド/パスを登録し、認証/認可フローを組み込む
- **Schema ファイル群**:用途別(POST、GET、PATCH など)の Pydantic モデル定義
- **Service スケルトン**:全メソッドで `NotImplementedError` を raise  

### 4. 動作確認
- アプリケーションを起動し、Swagger UI 上でエンドポイント一覧・スキーマ構成の表示を確認  

---

## 生成ファイル構成(例)
<!-- スケルトン生成時の出力ファイルとディレクトリ構造を示す -->
- `router/`  
  - エンドポイント定義、認証・認可フロー、Service呼び出し
- `schemas/`  
  - API用データモデル定義(入力用・出力用)
- `services/`  
  - ビジネスロジックのスケルトン(`NotImplementedError` のみ)
- `__init__.py` など初期化用ファイル  

---

## 設計ルールと要点
<!-- スケルトン生成時に守るべき設計ルールと重要ポイントをまとめる -->

### Router設計ルール
- HTTPメソッド別にエンドポイントを明確に分離
- 認証/認可設定はルート登録時に必ず明示
- 基本的な例外処理やステータスコードの枠組みを定義  

### Schema設計ルール
- Pydantic モデルで型定義し、必須/任意フィールドを明示
- 入力用(リクエスト)と出力用(レスポンス)を分離
- `description` は自然な日本語で記載しSwagger UIで活用
- 共通フィールドや型はベース Schema を作り継承する  

### Service設計方針
- 各メソッドの先頭で必ず `NotImplementedError` を raise
- 引数・戻り値の型定義は Schema に準拠
- 実装予定箇所に TODO コメントを残す  

### 認可パターン(例)
- 認可あり: ロールベース・トークン認証など
- 認可なし: 公開エンドポイントとして明示  

---

## よくある間違いと注意点
<!-- スケルトン作成・利用時に陥りやすいミスや注意点を列挙する -->
- Router と Schema でフィールド名/型が一致していない
- Swagger UI にスキーマが表示されない(モデルの未登録など)
- `NotImplementedError` のまま本番に反映してしまう
- Router に認可フローを書き忘れる
- ベース Schema を継承せず、重複定義が増える 

ここではあえてビジネスロジックは実装させません
まずインターフェース(Schema)を確定させSwagger UI にAPIを作ることで、以下のメリットが生まれます。

  • フロントエンドチームに「APIの型」を即座に共有できる
  • Swagger UI上でAPIが叩けるので、バリデーションの挙動を早期に確認できる

待ち時間を減らすための工夫です。

外枠ができたら、次は中身を作っていきます(STEP3)


STEP3: ビジネスロジックの生成(先にプランを書かせる)

Service層とDAO層を実装させます。

  • 使用プロンプト: ビジネスロジック作成プロンプト
  • 入力: STEP1の実装指示書
  • 出力: Service層 / DAO層の実装(+必要な関連修正)

ビジネスロジック作成プロンプト(サンプル)

このプロンプトがやっていること:

  1. APIのビジネスロジック(Service層、必要に応じてDAO層)を仕様に沿って実装する
  2. スケルトンがない場合は先にRouter/Schemaを生成する
  3. 実装プランを作ってユーザー承認後にコードを書く
  4. Service層は業務バリデーションやトランザクション管理を担当
  5. DAO層はデータ永続化のみ担当し、業務ロジックは持たない
  6. 実装後にSwagger UIなどで動作確認を行う
# ビジネスロジック生成

**目的**  
APIのビジネスロジック(主にService層、および必要に応じてDAO層)を実装するための手順とルールを示す。  
APIのスケルトン(Router / Schema / Service)が未作成の場合は、先にスケルトンを生成してから実装する。 <!-- このプロンプトが目指す最終成果物を簡潔に説明する --> 

---

## プロセス概要
<!-- ビジネスロジック実装の進行手順を大まかに説明する -->
1. **指示の受け取り**  
   実装対象APIの仕様・要件を取得
2. **プランニングフェーズ**  
   実装プランを作成
3. **ユーザー承認待機**  
   プランを関係者と確認
4. **実装フェーズ**  
   Service / DAO のコード生成
5. **動作確認**  
   Swagger UI等で検証  

---

## 実装指示に必要な情報  
<!-- 実装に必要な仕様情報を明示し、不足があれば質問で補う -->
不足があれば質問して補完する:
- 対象API(リソース名、HTTPメソッド、エンドポイント)
- 処理シーケンス(詳細ステップ、入力→処理→出力)
- 関連テーブル・DAO(利用予定メソッド、主外キー関係)
- 認証・認可要件(ロール / スコープ、公開 / 非公開)  

---

## プランニング前チェック
<!-- 実装前に必ず確認すべきスケルトンや依存関係の準備状況 -->
- APIが既に存在するか確認(Router / Schema / Serviceの有無)
- スケルトン未作成の場合は先にスケルトン生成
- 必要なDAOやモデルの準備状況確認(不足時は作成計画に含める)
- 外部依存(他サービス、メッセージング、ストレージ)の有無確認  

---

## プランニング(必須事項)
<!-- 実装に向けた詳細設計項目を整理するフェーズ -->
- **詳細処理フロー**  
  - 各ステップの目的、入力/出力、バリデーション、状態遷移、例外方針  
- **使用DAOとメソッド**  
  - 既存流用 / 新規作成、理由、I/O契約(引数 / 戻り値 / 例外)  
- **トランザクション境界**  
  - 開始 / コミット / ロールバックのタイミング、分離レベル、再試行戦略  
- **例外設計**  
  - 業務例外(4xx系) / 技術例外(5xx系)、リトライ可否、マッピング方針  
- **非機能要件・運用**  
  - 性能目標、同時実行とロック方針、監査 / トレーシング、レート制限  
- **参考実装(任意)**  
  - 類似APIや共通エラーハンドリングのリンク  

> プランはMarkdownで提示し、コードやSQLは含めない。必要なら疑似コード可。

---

## ルールと設計要点
<!-- 実装時に守るべき設計ルールと品質要件 -->

### Service層実装方針
- 入力はSchemaで受け、内部モデルへ変換
- 業務バリデーションはServiceに集約
- DAO呼び出しの前後条件を保証
- 例外は業務/技術で区別
- トランザクションはService層で管理  

### DAO層実装方針
- 永続化責務のみ、業務ロジックを持たない
- 単機能メソッド化(insert / update / delete / find)
- 型定義で引数・戻り値を明確化
- None/空配列の扱いを文書化
- インデックス活用、N+1回避  

### モデル・バリデーション設計
- 入力と出力モデルを分離
- 共通フィールドはベースモデル継承
- バリデーションは三層構造(Schema→Service→DB制約)
- descriptionを自然言語記載しSwagger表示に活用  

### トランザクションとパフォーマンス
- トランザクション境界は短時間
- 読み取り専用は外で実行
- 大量処理はバッチ/ページング
- キャッシュ戦略明記
- 冪等性/重複防止策  

### コーディングスタイル要点
- 命名規則統一(動詞+目的語)
- 早期return、ガード節活用
- 例外メッセージには原因・対処・場所
- 機密情報はログ/例外に出力しない
- テスト容易性を考慮し副作用分離  

---

## 実装チェックリスト
<!-- 作業の進捗確認や漏れ防止のためのチェック項目 -->
- 事前
  - [ ] スケルトンの存在確認
  - [ ] DAO/モデル準備完了
  - [ ] 不明点解消済み
- Service実装
  - [ ] Schema→内部モデル変換
  - [ ] バリデーション適用
  - [ ] トランザクション境界定義
  - [ ] 外部呼び出しのタイムアウト設計
- DAO実装
  - [ ] クエリ最適化
  - [ ] ページング/ソート設計
  - [ ] インデックス活用確認
- セキュリティ・運用
  - [ ] 認証/認可要件遵守
  - [ ] 機密情報マスキング
  - [ ] ログ/トレーシング設定
- テスト・検証
  - [ ] 正常/異常/境界ケース
  - [ ] 冪等性試験
  - [ ] パフォーマンス試験  

---

## 動作確認
<!-- 実装後にAPIの動作や安定性を検証するポイント -->
- Swagger UIでエンドポイントとスキーマ確認
- 手動リクエストで正常/異常動作確認
- トランザクション成功/失敗時の挙動確認
- ログ/トレースでDAO呼び出しの経路検証  

---

## 参考実装
<!-- 再利用できる過去のコードや設計例へのリンク -->
- 類似機能や共通部分へのリンク(共通ライブラリ、共通エラーハンドリング、共通DAOなど)  

以前はプラン無しでいきなりコードを書かせてましたが、手戻りが多かったため、
プラン→承認→実装 のフローを強制するようにしました。
これで認識ズレがかなり減りました。

ロジックができたら、次はテストを作っていきます(STEP4)


STEP4: pytestの単体テスト生成(正常系・異常系まとめて)

pytestで単体テストを作らせます。

  • 使用プロンプト: 単体テスト作成プロンプト
  • 入力: STEP1の実装指示書
  • 出力: pytestのテストコード(+必要なテストデータ)

単体テスト作成プロンプト(サンプル)

このプロンプトがやっていること:

  1. APIがあるか確認
  2. 正常系・異常系・境界値などのテストプラン作成
  3. fixtureやモックでテスト環境準備
  4. pytestでテストコードを作成
  5. 実行して結果やDB状態を検証
  6. 命名規則や品質チェックリストに沿ってテストを整備
# 単体テスト生成
<!-- APIエンドポイントの単体テストをpytestで設計・実装するためのガイド -->

**目的**  
<!-- このプロンプトが目指す最終成果物を簡潔に説明する -->
APIエンドポイントの単体テスト(pytest)実装方法とルールを示す。  
対象APIが未作成の場合は、スケルトン生成 → ビジネスロジック実装 → 単体テスト作成の順で進める。  

---

## プロセス概要
<!-- テスト設計から実装・実行までの大まかな流れを示す -->
1. **前提確認**  
   - API が存在すること(Router / Schema / Service が用意されている)  
   - 必要なビジネスロジックが実装されていること
2. **テストプラン作成**  
   - 対象ケースの洗い出し(正常系・異常系・境界値・並行性・冪等性)
3. **テスト実装**  
   - fixture の準備(DB 初期化、API クライアント、モック)  
   - テストデータ作成(外部キー順序等を考慮)  
   - テストケース作成(パラメータ化や共通ヘルパの設計)
4. **テスト実行と結果確認**
5. **クリーンアップと整備**  
   - テスト後のデータ/環境の戻し、テストコードの整備(リファクタ・コメント追加)

---

## テストアーキテクチャ
<!-- 単体テストの構成要素とデータフローを概観する -->
- **データフローの概観**  
  - リクエスト → Router → Service → DAO → データストア → レスポンス(とログ)
- **主要コンポーネント**  
  - pytest 本体(テストランナー)  
  - fixture(DB接続、テストクライアント、モック)  
  - テスト対象の Service/DAO 関数や Router エンドポイント
- **外部依存**  
  - 外部 API / メッセージング / ストレージ等は基本モック化する(接続テストは別途統合テストで実施)

---

## 必要な前提環境
<!-- 実行者が迷わないように環境依存と準備手順を整理 -->
- ローカル環境またはテスト用コンテナの起動手順(README に記載)
- テスト用 DB の初期化コマンド / マイグレーション適用手順
- 必須環境変数の一覧(ダミー値例を含めて記載)

---

## テストデータ管理
<!-- テスト用データの構造と生成・管理方法を示す -->
- **テストデータファイル構成**  
  - 例: tests/data/normal/, tests/data/error/, tests/data/boundary/
- **外部キー考慮**  
  - 依存順(親テーブル → 子テーブル)で初期化するfixtureを用意
- **タイムスタンプ扱い**  
  - 固定値(例: 2020-01-01T00:00:00Z)を使うか、freezegun 等で時刻を固定する
- **テストデータの再利用性**  
  - 共通データはfixture化し、個別ケースはオーバーライドで対応

---

## テストケース設計
<!-- 正常系・異常系・境界値など多角的にケースを設計する -->
- **正常系パターン**  
  - 標準入力で期待レスポンス・DB変化が起きることを確認
- **異常系パターン**  
  - 必須パラメータ欠落、型不一致、認可エラー、権限不足、リソース未存在など
- **境界値パターン**  
  - 最大長、最小長、ページングの端、タイムアウト等
- **パラメータ化テスト**  
  - @pytest.mark.parametrize を使い複数ケースを効率的に実行
- **外部サービスモック化**  
  - 正常応答、接続エラー、タイムアウト、異常コード(500/502 等)を最低3パターン用意
- **並行性 / 冪等性**  
  - 同時リクエストや同一操作の重複送信を想定したテスト

---

## 検証方法(実行時に必ず確認すること)
<!-- テスト実行後に確認すべき結果や状態をチェック -->
- ステータスコード確認(200, 201, 204, 400, 401, 403, 404, 500 等)
- レスポンスボディのスキーマと値検証(必要項目、型、一意性)
- DB 状態の確認(該当レコードの有無・更新内容)
- ログ出力(必要に応じて)、トレース ID の流れ確認
- 後片付け(テスト終了時に DB が初期状態に戻ること)

---

## テストファイル・クラス命名規則
<!-- テストコードの読みやすさと整理を保つ命名ルール -->
- ファイル名: `test_<機能名>.py`(例: test_user_api.py)
- クラス名: `Test<機能名>`(機能単位でまとめる場合)
- メソッド名: `test_<シナリオ>`(例: test_create_user_success)
- fixture 名は `fixture_<目的>`、モック名は `mock_<外部名>` のように役割が明確な命名を推奨

---

## チェックリスト
<!-- テストの網羅性や品質を確保するためのチェック項目 -->
- **基本要件**  
  - [ ] テストクラス/fixture が正しく定義されている  
  - [ ] 正常系 / 異常系 / 境界値 が網羅されている
- **DB 整合性**  
  - [ ] 外部キー制約を満たす初期化順序で fixture が動作する  
  - [ ] テスト終了後に DB が初期状態に戻る(ロールバック・truncate 等)
- **モック適用**  
  - [ ] 外部 API はすべてモック化されている(統合テスト除く)  
  - [ ] モックは期待するエラーケースも網羅している
- **品質指標**  
  - [ ] カバレッジ目標を満たす(目標値はプロジェクト定義)  

---

## トラブルシュート(よくある失敗と対処)
<!-- 単体テストで発生しがちな問題とその回避方法 -->
- DB の初期化が漏れる → fixture のスコープや順序を見直す
- モックが実際の I/O を行ってしまう → モックのパス指定/パッチ箇所を確認
- テストが遅い → 重いセットアップを共有 fixture に移す、不要なログを抑制
- 非決定的な順序依存 → 各テストを独立に、初期状態に戻す仕組みを徹底

---

## 参考リンク
<!-- 関連ドキュメントや外部リソースを提示 -->
- pytest 公式ドキュメント(https://docs.pytest.org/)
- FastAPI Testing ガイド(公式ドキュメント内の Testing セクション)
- pytest-mock の使い方リファレンス

「既存実装を見に行く」指示が効いて、既存の書き方に寄せたテストを出してくれます。
また、正常系だけでなく異常系(バリデーション、NotFound、権限エラーなど)ももれなく提案してくれるため、人が書くよりも網羅性が高くなることもしばしばです。

テストまで揃ったら、最後にプロンプトやドキュメントを育てます(STEP5)


STEP5: 各種プロンプトとドキュメントを更新する(使うほど良くする)

最後に軽く振り返って、

  • 生成がブレたポイント
  • 指示が曖昧だったポイント

をプロンプトや copilot-instructions.md に反映します。

  • 使用プロンプト: ドキュメント更新プロンプト
  • 入力: 直したい箇所を箇条書き

ドキュメント更新プロンプト(サンプル)

このプロンプトがやっていること:

  1. .github/copilot-instructions.md.github/prompts/*.prompt.mdREADME.mdを対象
  2. 未指定でも自動的に改善点を検出
  3. アーキテクチャ・ワークフロー・規約・結合仕様の記述を最新化
  4. 古い情報を置き換え、表記を統一
  5. 必要があれば既存テンプレとインテリジェントにマージして冗長性を排除
# ドキュメント更新プロンプト(サンプル)

**目的**  
AIエージェントが迅速かつ生産的に動作できるよう、コードベースから抽出可能な重要知識を反映し、以下の対象ファイルを最新化する。  
- `.github/copilot-instructions.md`  
- `.github/prompts/*.prompt.md`(カスタムテンプレート各種)  
- `README.md`  
対象ファイル以外の修正は禁止。
<!-- このプロンプトが目指す最終成果物を簡潔に説明する -->

---

## インプット(任意)
<!-- 改善対象や修正箇所を事前に指定できる -->
- 直したい箇所(箇条書き)  
※ 未指定の場合は対象ファイルの現行内容を解析し、ブレや曖昧表現、構造不足を自動検出。

---

## 更新対象項目
<!-- どの領域の記述を更新するかを定義 -->

### 全体像のアーキテクチャ
<!-- フレームワークやレイヤー構成の補足と役割説明の用語統一 -->
- フレームワーク・主要レイヤー構成の記載漏れや不明瞭な部分を補足
- コンポーネントの役割説明を簡潔かつ一貫性のある用語に

### 開発者ワークフロー
<!-- ファイルの中身だけでは明らかにならない重要な開発手順を記載 -->
- ビルド手順
- テスト実行方法
- デバッグ方法

### プロジェクト固有の規約とパターン
<!-- 命名規則や構造パターン、禁止事項の統一 -->
- 命名規則、モデル継承、DAO構造パターン、予約語対応方針
- エラーハンドリングや認可ポリシーの統一化
- 実装時の禁止事項や推奨事項

### 結合ポイントとコンポーネント間通信
<!-- 外部サービス連携やモジュール間の通信仕様を明確化 -->
- 外部サービス連携仕様(認証基盤、メッセージキュー、REST API等)
- モジュール間インターフェースの概要
- データ/イベントの流れ

### 規則事項
<!-- AI応答や出力形式、保守ルールに関する指針 -->
- AI応答言語ルール(必要に応じて明示)
- 出力形式ルール(Markdown、コードフェンス、断言形)
- 保守上の必須ルール(古い記述削除時の理由明記)

---

## 出力形式
<!-- ドキュメント形式の指定とプロンプト化の準備 -->
- Markdown構造を使用して簡潔で実用的な指示を記述
- 発見した知識と例を体系的に構造化し、再利用可能なプロンプトテンプレートとしてまとめる

---

## 追加要件
<!-- 更新作業時の制約とマージ方針 -->
- 対象ファイル以外は出力に含めないこと
- すでに該当テンプレートファイルが存在する場合は、インテリジェントにマージを行い、価値ある既存コンテンツを保持しつつ、古くなったセクションを更新する
- マージ時は冗長性を避け、最新のコード構造やワークフローと整合性をとること

これをやると次回 同じミス を踏みにくくなります。
また、プロンプトやドキュメントが古くなり陳腐化すると精度が落ちやすいので、このSTEPは業務フローに組み込んで「必ずやる」運用にしています。

👍 導入してみて良かったこと(効いたやつ)

体感で効いたのはこのあたりです。

  • 単体テスト作成がかなり楽になった
    • テストって地味に時間吸われるので、ここが軽くなるだけで開発者の幸福度は爆上がりです!
  • API仕様共有が早い
    • STEP2の時点でSwaggerが立つので、フロントエンドチーム等の他チームを待たせることがない
  • 品質が揃う
    • 未経験メンバーでも、手順通りに進めれば品質が高いPRが出せるようになった
    • レビューでの指摘事項が減った

結果として、Copilot Agent が「あると便利」から 「いないと困る」 くらいのポジションになりました。

🎬 次回予告

第2弾では、さらに精度と自動化レベルを上げるための施策を紹介する予定です。

  • AIにコードレビューさせる(観点を固定してブレさせない)
  • AIにテストを自動実行させて、結果もレビューさせる

続きもぜひ読んでいただけると嬉しいです!フォローもお待ちしています〜!🙇

20
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?