はじめに(Why)
数年運用している業務システムで、ずっとモヤっとしていた問題がありました。
- 機能は動いているが 仕様書がない
- 「これは仕様?それともたまたま?」がコードを読まないと分からない
- 特に 例外系・権限・二重処理 で、担当者ごとに解釈が違う
今回対象にしたのは「ポイント交換」機能です。
- 複数の交換先がある
- 最小/最大、換算率、権限など制約が多い
- 外部連携失敗時の扱いが重要
正直、毎回コードを追うのはしんどく、
「人間が読める仕様」に落としたいと思いました。
ただし、現実は既存システム。
新規開発のように Gherkin から書くのは無理です。
そこで試したのが、AIを使った逆Gherkin化でした。
Gherkin / BDD とは(最小限)
- Gherkin:Given / When / Then で振る舞いを書くフォーマット
- BDD:仕様とテストの認識を揃える考え方
今回は 「テスト自動化」ではなく「仕様の可視化」 が目的です。
いきなり Behave / Cucumber を回すことはしません。
なぜ「逆Gherkin化」なのか
新規開発なら、
仕様 → Gherkin → 実装
が理想です。
でも既存システムでは、
実装(=事実) → 仕様
の方が現実的です。
- 正解は「動いているコード」
- 仕様書よりコードの方が新しい
- 暗黙知を炙り出したい
逆Gherkin化は、既存システムにBDDを途中導入する現実解だと感じました。
対象にしたシステム(抽象化)
- バックエンド:Python系API
- フロント:Web / アプリ相当(別リポジトリ)
- 機能:ポイント交換(複数の交換先)
この機能の特徴は、
- 残高チェック
- 最小 / 最大交換量
- 換算レート(デバイス差あり)
- 権限(購入・利用実績によって変化)
- 二重処理防止
- 外部連携失敗時のロールバック
仕様の塊みたいな機能でした。
実際にやった手順(How)
Step1:対象を絞る
最初から全部はやりません。
- if / else が多い
- ステータス分岐がある
- 例外が多い
この条件に当てはまる 交換フロー1種類から始めました。
Step2:AIに「調査役」をやらせる
重要なのは プロンプト設計です。
「Gherkinにして」だけだと、ほぼ失敗します。
実務で使っている調査依頼プロンプト(汎用化)はこちらです。
あなたは既存システムの仕様調査担当です。
仕様書が存在しない「ポイント交換」機能について、コードから振る舞いを読み取り、
人間が理解できるようにGherkin(Given/When/Then)で列挙してください。
目的:
- 仕様の全体像と差分を把握する
- レビュー・合意可能な仕様書を作る
ルール:
- 技術用語(クラス名、DB、HTTPなど)は使わない
- ユーザー視点・業務視点で書く
- if/elseをそのまま列挙しない
- 正常系と代表的な異常系を含める
- 断定できない点は「要確認」と明示する
出力:
1) 発見した交換種類と制約
2) Gherkin(Feature / Scenario)
3) 要確認事項
ポイントは 「断定しない」「要確認を出させる」 です。
Before / After(ここが一番反応が良かった)
Before(擬似コード)
if not user.can_exchange:
raise Forbidden
if amount < MIN_AMOUNT:
raise ValidationError
if lock_exists(user_id):
raise Conflict
deduct_points(user, amount)
try:
external_grant(converted_amount)
except ExternalError:
refund_points(user, amount)
After(Gherkin)
Feature: ポイントを外部サービスへ交換する
Background:
Given ログイン済みの会員である
And ポイント交換が許可されている
Scenario: 正常にポイントを交換できる
Given 利用可能ポイントが1,000ptある
When 500ptの交換を申請する
Then 利用可能ポイントが500pt減る
And 外部ポイントが付与される
Scenario: 交換権限がない場合は交換できない
Given ポイント交換が許可されていない
When 交換を申請する
Then 交換できない旨が表示される
And ポイントは減らない
Scenario: 外部付与に失敗した場合は元に戻る
Given 交換申請が受け付けられている
When 外部付与が失敗する
Then ポイントは元に戻る
And 利用者に失敗が分かる
コードでは「当たり前」だった分岐が、
仕様として初めて言語化されました。
やって分かった:AIは万能じゃない(Gotcha)
Gotcha1:内部仕様を仕様だと誤解する
- TTL
- リトライ回数
- バッチタイミング
AIは全部 Then に書きたがります。
👉 Gherkinは「観測可能な結果」だけにする
👉 内部都合は「実装メモ」へ逃がす
Gotcha2:提供終了・移行中の機能が混ざる
画面では終了案内が出ているのに、
Scenario上は「普通に使える」扱いになっていました。
👉 @deprecated や @disabled のタグで整理
👉 「現行 / 過去 / 移行中」を明示
Gotcha3:用語が揺れる
「残高」「利用可能」「付与」「交換」などが混在。
👉 用語を Feature冒頭で固定
👉 Glossaryを別途作成
なぜ最初からテストにしなかったのか
最初からBDDテストにすると、
- 仕様が固まっていない
- 要確認が多い
- テストが壊れやすい
今回はあえて 「仕様の可視化」だけ に集中しました。
テスト化は、
合意が取れた Feature から段階的にで十分でした。
導入して得られた効果
- 仕様確認が「コード読む」→「Scenario読む」に変わった
- 例外系の認識ズレが減った
- レビュー観点が整理されたことで、1件あたりのレビュー往復回数が
- 逆Gherkin化前:平均3〜4往復
- 逆Gherkin化後:平均1〜2往復
程度に減りました(体感ベース)。
- 新規メンバーのキャッチアップが楽になった
特に「これは仕様ですか?」という会話が
Gherkinを指差すだけで済むようになったのは大きかったです。
まとめ
- 逆Gherkin化は 既存システムにBDDを入れる現実解
- AIは「仕様の叩き台作成」に非常に強い
- ただし レビューと要確認整理は人間必須
- 全部やらず、重要フローだけで十分
もし既存コードの仕様化に悩んでいるなら、
テストを書く前に、逆Gherkin化を強くおすすめします。