ユニットテストが刺さらない

通常のソフトウェアなら「入力 A を渡せば出力 B が返る」と断言できるのでユニットテストが書けます。LLM を組み込んだアプリにはその前提がありません。同じプロンプトで呼んでも返ってくる文章は毎回異なる。プロンプトを 1 行直したとき、他のケースの出力がどう変わったかは実行してみるまで分からない。

この非決定性が LLM アプリのテストを難しくします。アサーションを書きにくい。書いても壊れやすい。だからといってノーテストでプロンプトを変更し続けるわけにもいかない。

ゴールデンデータという発想

解決策の一つがゴールデンデータです。「この入力に対してこの出力は合格」と人間が一度承認し、その出力をファイルとして git 管理します。スナップショットテストや approval testing と呼ばれてきた手法を、LLM の特性に合わせて応用したものです。

データの置き場を三つに分けるのが骨格です。

テスト入力      git 管理       シナリオ定義(YAML など)
生成結果        .gitignore     LLM を実行するたびに上書きされる
ゴールデン      git 管理       人間が承認した出力のコピー

生成結果を git 管理「しない」のがポイントです。実行のたびに変わるものをコミットすると diff がノイズだらけになります。承認したものだけをゴールデンとして固定します。

運用フロー — run / compare / promote

フローは三段階です。

1. run     → 現在のプロンプトで LLM を実行し、生成結果を保存
2. compare → 生成結果とゴールデンを比較し、差分や品質低下を確認
3. promote → 問題なければゴールデンへコピーして commit

promote した後は、次回以降の実行で生成結果とゴールデンを突き合わせるだけで「前より悪くなっていないか」を機械的に判定できます。

プロンプト変更が git diff として可視化される

この設計の最大の利点は、プロンプト変更の影響が git diff として現れる点です。

- 「マーケット拡大の機会がある」と判断した理由:...
+ 「採用難易度が高い」と判断した理由:...

コードレビューと同じ流儀で、プロンプト変更の前後で何が変わったかをレビューできます。「意図した変更」と「意図しない副作用」を分けて判断できることが重要で、CI でゴールデンとの乖離を検出したらレビューを要求する、というフローが成立します。

昇格は「確認してから」が鉄則

promote 自体はただのファイルコピーなので、いつでも実行できてしまいます。だからこそ「比較して問題なしを確認してから昇格する」を運用ルールにします。

sim compare --strict            # 差分と品質を確認
sim promote --scenario 001      # 確認後に昇格
git commit -m "promote 001: プロンプト改訂後の出力を承認"

commit メッセージに「なぜ承認したか」を書く習慣が、後になって「なぜゴールデンが変わったのか」を追うときに効いてきます。ゴールデンの変更履歴は、プロンプトの変更履歴と対になる「出力の変更履歴」になります。

まとめ

  • LLM 出力は非決定的で、従来のアサーションベースのテストが書けない
  • 人間が承認した出力を「ゴールデンデータ」として git 管理する
  • 生成結果は git 管理せず、承認したものだけを固定する
  • run → compare → promote の三段階で、出力の変化を意図的にコントロールする
  • プロンプト変更の影響が git diff として可視化され、レビュー可能になる