Skip to content

LLM時代のメタテスト テストコードで担保したい意図をテストする

📖 フラクタルと方法論 | 次のページ: メタテストは人間の規範である

射程

  • LLMがテストを修正する際に実装の「本来の意図」ではなく現在の実行結果を期待値として書き入れてしまう問題に対し、ADRやSDDはいずれも最終的な品質担保をLLMの善意と報酬関数に委ねており不完全
  • テストコードのデータセットや結果セットの傾向そのものをテストするメタテスト——「テストの憲法」——により、実装当時の設計意図を上位規範として固定できる

主張の確信度(命題確率伝播による計算値)

凡例 — b・d・u・E の読み方

各主張(claim)は記事の frontmatter に構造化されており、belief-propagation(Subjective Logic + Defeasible Logic による命題確率伝播エンジン)で全Wikiの命題を一つの依存グラフとして一括計算した値を表示している。
b = belief(確信)/ d = disbelief(非確信)/ u = uncertainty(不確実性)。三値は常に b + d + u = 1。
E = 期待値(E = b + a·u。a = base rate(事前確率)、省略時 0.5)。
「著者確信度」(base_confidence)は書き手の主観的確信度。出典種別(source_type)による割引と、前提(premises)・反証(rebutted_by)からの伝播を経て、上記の計算値になる。
タグの目安: 高 = E ≥ 0.75 / 中 = 0.5 ≤ E < 0.75 / 低 = E < 0.5

  • 中 0.66wiki95-C1
    LLMがテストを修正する際に実装の本来の意図ではなく現在の実行結果を期待値として書き入れてしまう問題に対し、ADRとSDDはいずれも品質担保をLLMの善意と報酬関数に委ねており不完全である
    b=0.315 d=0.000 u=0.685 a=0.500 E=0.658著者確信度 0.70・出典 wiki_original
  • 中 0.55wiki95-C2
    テストコードのデータセットや結果セットの傾向そのものをテストするメタテスト——テストの憲法——により、実装当時の設計意図を上位規範として固定できる
    b=0.092 d=0.000 u=0.908 a=0.500 E=0.546著者確信度 0.65・出典 wiki_original
    支持 ← wiki95-C1

ハーネスエンジニアリングの実践 — テストの憲法

キーワード

メタテスト ハーネスエンジニアリング 報酬関数 意図の担保 テストの憲法 ADR Spec Driven Development フィクスチャテスト 傾向テスト


2026/04/05に公開

タグ: Test llm ハーネスエンジニアリング フィクスチャ

カテゴリ:idea この文章はそこそこ長いエッセイのようなテイストをとっています。

長いので結論だけ書くと、「LLMでテストコードを書いて開発を進めるなら、テストコードのデータセットや結果セットの傾向をテストするメタテストという手法が非常にマッチしているかも」という内容です。

なお、この記事の執筆にはLLMを微細な添削以外に一切使っていません。 ちなみに英文の翻訳のよのな文体は筆者の手癖です。


先日、ダッシュボードをAIに作らせることにした。 最近はLLMの進歩によって、自分専用のダッシュボードを作るのが本当に簡単で、とても素敵なものが作れる。 私が作りたかったのは、まさにJIRAのバーンダウンチャートがサブタスクの完了ごとにダウンしていかないという問題を解決するため、サブタスクの完了につれてチャートがダウンするものを作りたい。欲を言えばもっともっと機能を追加したい。

ところが、いくつか機能を追加していくうちに、片方の機能を作った時にもう片方の機能が失われる、デグレが頻繁に起きるようになった。

もちろん、単体テストや統合テストのようなテスト(私は実データをローカルに入れてそこからテストするフィクスチャテスト)はとりいれていて、それらのテストはたくさんある。 それでもなお、機能追加やテスト用のデータの再収集によってテストが壊れるから(単体テストのような関数の保証ならそうそう簡単に壊れないと思うが、フィクスチャテストは簡単に壊れる)そのたびにLLMが期待値を"テストが通るように"直すのだが、この時にコードに宿る"本来の目的"、"文脈"を思い出すことができないようで、ただただ現在の実行結果を期待値として書き入れてしまうようだった。

これが特に顕著に現れるのは、フィクスチャとなるデータに欠損があるときに、気づく方法がなくて実際に動かして初めて分かる、といった形で表出する。 LLMは自分の勤めを果たしているが、ただ満たすべき品質基準に気づかない。

この問題に対処するために、世間ではADR(Architectures Decision Record, アーキテクチャに関する意思決定の記録)として時系列にまとめるといったテクニックも流行っているようだ。 実装当時の意思決定の中で磨かれたコンテキストがあれば、LLMはその文脈に沿ってうまくやることを期待している。

また、Spec Driven Development(仕様駆動開発)とどちらが良いかという議論が活発になされているようだ。

このアプローチはどちらも一見悪くないが、私にはどちらも罠が潜んでいるように見える。まずADRの罠一つに、品質管理の最終ゲートをLLM(の善意)に任せている。どこかひとつでも綻びがあれば、誤った報酬関数によって明後日の方向に向かってしまう可能性がある。これは後のSpec Driven Development(仕様駆動開発)へと駆り立てる。もう一つの問題は、ADRは時系列データであって、最新の状態のスナップショットではないことだ。これもSpec Driven Developmentが好まれる合理的な理由として納得できる。

一方で、Spec Driven Developmentはシンプルにドキュメント過多で、とても保守しきれずに破綻していく、思うように開発の速度がでない、いやそもそもSDDは1タスク分の計画をきっちり立てろという方法論であって、長期間保存し続けるドキュメントではないといった議論もある。これらの開発手法の詳細は本論の趣旨ではないので傍に置く。

いずれにせよ、どちらも最終的な品質の担保はLLMの善意と報酬関数(テストが通るか落ちるか)に委ねられていて、不完全であるように思えた。

そこで私は一つの方法を思いついた。メタテストだ。 「テストコードは本来の設計意図を満たせているか?」

手法はこうだ。 統合テストのシナリオの一つ一つ、あるいはユースケースのひとつひとつのような単位にはおそらく、機能が目的を果たしたい期待が込められている。 通常テストはデータの入力に対する結果の完璧な対応表で、データごとの相関や結果ごとに対する相関は全く検査対象ではない。

そこで、入力されたデータと結果セットの傾向をテストしてしまえばいいのではないか?ということ。

具体的には、「タスクにはサブタスクがたくさん紐づいている」「サブタスクは通常毎日どれかは完了状態に移動する」「したがって、タスクの進捗は基本的には毎日進み続ける」

これをテストするには、 「結果セットは前の日の進捗よりも進んでいる」ことをテストすれば良さそうだ。 ただし、実際のところ偶然進捗がなかったということもありえて、それらを一つ一つ例外としてマークするのは大変だ。 代わりに、「全体をみて、進捗が進んでいる日が80%くらいを越えていればよい」みたいなアレンジを加えれば、さらに現実のユースケースに適用しやすいだろう。もちろんこの割合は現実のユースケースに適した値を採用すること。80である必要はないし、全体に対する割合で検出しなくてもよい。

そもそも、取得したデータセット(サブタスクの詳細)がタスク一覧を確認したときに見えたサブタスクのトータルを大きく乖離しているということもあって、これは「サブタスクが暗黙的に設定されたLimitによって不足していて、そもそも取得できていなかった」という現象の表れであったりして、「フィクスチャテストのために用意したデータセットは期待通りか?」を検証するだけでよかったりするかもしれないが、いずれにせよそれらの問題をすべて網羅するより、全体の傾向に品質基準を設けるというのは悪くないアイデアに思える。

実のところ、メタテストというのは私のオリジナルのアイデアではない。そればかりか、私が初めてメタテストに出会ったのは6〜7年前、ソーシャルゲームの開発に従事していた頃の話だ。その頃は品質担保のためのテストについてずいぶん頭を悩ませていた。 結局、その頃のメタテストの私の評価とはいうと、「テストを書き換えてもなお意図を表せているかどうかについて担保できるかはわかった。でもいずれにせよテストコードの大量の書き換えを開発プロセスに織り込み済みにするには締め切りに間に合わない」というもので、現物合わせのでっち上げ品質に落ち着く、壊れたテストはコメントでなぜ落ちているのかを書き残して無視するというのが当時の限界だった。 しかし、LLMは勤勉かつ高速で、あらゆるテストを通すことにかけては比類がない。 メタテストから意図さえも削り取ってしまう可能性は依然として残されているから、メタテストの側には口酸っぱく「ユーザーの承認なしにメタテストを改変してはいけない」のような注意書きをしなければいけないかもしれないが、メタテストはテストの憲法、テストは実装コードに対する法、コードは偶然現在の実現方法であって、上位の法や憲法を満たすならより良いものに書き換えて良い とするのは筋が良さそうに見える。

ここまでのことを行うと、何かのバグを発見してトラブルシューティングを依頼すると、「その問題の仮説は間違っていて、本来の原因はこちらでした」と解説付きで修正してくれることさえあって、私は小さな感動を覚えた。

LLMの力が良い方向に発揮し続けるように工夫するのがハーネスエンジニアリングなら、メタテストは一つのハーネスとして機能するかもしれない。

ということで、一言でいうなら、「メタテストはいいかもしれない」



📖 次のページ: メタテストは人間の規範である

関連ドキュメント

果物リン (@FruitRiin) と、賢王*****(Claude)の対話から生まれた書架。