世界を動かす技術を、日本語で。

テスト駆動開発のための私のエージェントスキル

概要

  • 現在のAIエージェントはテスト作成が苦手
  • 多くの人間によるテスト例も低品質
  • Kent BeckのCanon TDDが有効な指針
  • 独自のSpecify-Encode-Fulfillループを提案
  • テスト設計・ソフトウェア設計レビューで品質向上

AIエージェントとテスト作成の現状

  • 2026年5月時点 では、AIエージェントによるテスト作成の品質が低水準
  • 曖昧・難解・過剰・ハック的・非効率・自己満足的・無意味なテストが多発
  • 人間のテスト例自体が悪い影響、教師の指導も不十分
  • 教育・実務現場ともにテスト文化の課題

TDD指針としてのKent Beck's Canon TDD

  • Kent Beck's Canon TDD の単純な指示だけでAIのテスト作成能力が大幅向上
  • Canon TDDの流れ
    • 現在のTDDセッションの範囲内で仕様リスト作成
    • 各仕様を自動テストとして実装
    • テスト失敗を解消するために必要最小限のコード変更
      • 推測的コーディングの回避
    • 振る舞い変更のコミット後のみリファクタリング
      • 振る舞い変更とリファクタリングの混在禁止
    • 仕様リストが空になるまで繰り返し

Specify-Encode-Fulfill(SEF)ループ

  • Specify :作りたいものの仕様策定
  • Encode :仕様を自動テスト(実行可能な仕様)として記述
  • Fulfill :仕様を満たすコード実装
  • SEFはTDDの本質を高い視点で捉えるための代替フレームワーク

テスト設計・ソフトウェア設計のレビュー

  • テスト設計自体の質向上には Test Design Review スキルを別途導入
    • 別エージェントによるバイアス回避
    • 設計原則違反の検出・修正提案
  • 一般的なソフトウェア設計原則の違反も Software Design Review で確認
    • 「ものごとをそのまま呼ぶ」など基本原則の徹底
  • テストが書きにくい場合は「キッチンを片付けてから料理する」発想でリファクタリングを検討

結論とAI活用の本質

  • 100%満足できるテストは未達成だが、TDDスキル導入で大幅改善
  • 時代を超える普遍的な原則AI の組み合わせが最大の生産性向上要因
  • 新技術が登場しても、基本原則は不変で有用

Hackerたちの意見

この記事には日付があった方がいいね。最近の情報っぽいけど(インターネットアーカイブでは5月29日にキャッチされたみたい)、モデルやエージェントが進化するから、すぐに古くなっちゃう情報なんだよね。(最近は、Claude CodeとCodexに「uv run pytestでテストして、赤/緑TDDを使え」って言うだけで、いい結果が出てる。)

私もそう思うけど、モックに偏りすぎてるのが嫌だな(これはトレーニングデータに過剰に表れてるのは認めるけど)。

プロンプトエンジニアリングはすぐに古くなっちゃうね。今どき「あなたはエキスパートのソフトウェアエンジニアです。間違いを犯さないでください」なんて言わないよね(笑)。個人的な体験として、大きなプロンプトやスキルはコンテキストウィンドウの予算を消費しちゃうことが多いし、エージェントは現在のタスクにあまり関係ないスキルでも使おうとすることが多い。だから、スキルが多すぎると、どれが必要かをチェックボックスで確認するのに時間がかかっちゃうんだよね。

これが今週のAGENTS.mdの一部だよ(FDEをプレイ中で、クライアントのためにカスタムワークフローを実装して、20倍の生産性を実現した)。# Pythonツール - uvを使ってPython環境と依存関係を管理する。 - uv runでPythonスクリプトやコマンドを実行する。 - コードのテストにはpytestを使う。 - 複雑な入力空間やエッジケースをテストする必要があるときは、hypothesisライブラリを使ってプロパティベースのテストを行う。 - pyproject.tomlを直接編集しない。代わりに、依存関係を管理するためにuv adduv add --devを使う。 - コードの品質とリンティングにはruff、ty、prek、wilyを使う。 - 過度なキャスティングは避ける。頻繁に型をキャストする必要があるなら、もっと適切な型を使うようにコードをリファクタリングすることを考えてみて。キャスティングは外部システムとインターフェースする境界層でのみ行うべき。 - コードに変更を加えた後は、適切なツールを実行して品質基準を満たしているか確認する。 - バグやリグレッションに遭遇したら、テストを書くことや、将来的に同じことが起こらないようなコードを作ることについて真剣に考える。 - コマンドラインインターフェースを作成するときは、デバッグに役立つログ出力を提供する--verboseフラグを追加する。 - コードを作成する前に、問題を解決するための5つの異なるアプローチを考えて、それらを効果的な順に並べる。その後、最適なアプローチを選んで実装する。 - 書くコードにはすべてテスト駆動開発(TDD)を使う。実装コードを書く前にテストを書く。 - 重複を避けるために、conftest.pyファイルにpytestフィクスチャを集める。 - 可能な限り実際のコードをテストすることを優先する。絶対に必要なときだけダブルやmonkeypatchを使う。モックはできるだけ避ける。 - pytestのmonkeypatchを好む。 - テストが失敗したら、まずuv run pytest --last-failedを使って最後に失敗したテストを実行する。 - 作成するすべての関数やクラスにはnumpyスタイルのドックストリングを使う。 - 関数のドックストリングには例を提供するためにドクトテストを含める。 - すべての関数パラメータと戻り値の型ヒントを使う。 - 失敗の洞察を提供するためにロギングを使う。デバッグにはprintを使わない。スタックトレースを隠すためにロギングを使わない。

参考までに、レスポンスヘッダーには以下が含まれています: Last-Modified: Fri, 22 May 2026 19:08:09 GMT

すべての記事には日付を入れるべきだよね!

いい指摘だね!日付を追加するよ。

https://github.com/jasonswett/llm-skills/blob/main/tdd/SKILL... にはタイムスタンプがあるね(2026年3月14日現在)

ここでスキルを使うのは間違ったアプローチだと思う。LLMはすでにTDDが何か、どうやってやるかを知ってるから、オブジェクト指向プログラミングと同じようにね。もしこれがスキルにエンコードされてるとしたら、そのスキルはLLMがやるすべてのことにロードされなきゃいけない。これはAGENTS.mdを通じて直接指示を出すのが一番いい数少ない領域の一つだと思うし、ここで問題を強制するためにあまり指示は必要ないと思う。でも、OPは自分のエージェントをすごく特定のやり方で動かそうとしてるだけだと思う。それも悪くないよね。 > 5. テストを見せて、続ける前に承認を求めてください。

スキルはただのマークダウンファイルだってことをみんな忘れがちで、TDDが意味を持つとは思わない。これはカスタムコードベースやあまり使われない道を進むときに特定のニッチ向けのものだと思うし、今後の教訓を保存するためのものだよね。でも、みんな自分のやり方を選ぶ自由があるし、私たちが知らない方法で必要になることもあるかもしれない。

私の経験では、確かにLLMはTDDやOOPについて知ってるけど、教えない限りその知識に基づいて行動するわけじゃないんだよね。もちろん、互いに矛盾することをたくさん「知っている」わけだし。

エージェント開発においてTDDは理論上は素晴らしいけど、トークンコストが膨れ上がるのにすぐ気づくよね。よく機能を作った後に、それが再利用されたり削除されたり、コードがリファクタリングされたりするから。TDDだと、かなり負担がかかって、進行速度が遅くなっちゃう。特にマルチエージェントのセットアップがあると、TDDを試した後はウォーターフォールアプローチの方がいいと思う。あと、いくつかのケースでは、テストが実際に書かれたコンポーネントをテストしていない表面的な幻覚だったり、コンテキストが壊れて誤ったポジティブを引き起こして、意図しないリファクタリングを引き起こすこともあった。

でも、その再利用や削除は、彼が示しているSEFフレームワークに従うことで避けられるものだよ。強力なフレームワークの中でTDDを使うとトークンコストが膨れ上がるという考えには反論したい。もし機能が再利用されたり削除されたりリファクタリングされたりするなら、トークンを消費する前に仕様がしっかり考えられていなかったと言えると思う。私たちはすぐに間違ったことをたくさんやりたがるけど、もっと正確なことをゆっくりやった方がいいかもしれないね。

私の経験は逆だな。TDDはガードレールを保ってくれて、自信を持ってリファクタリングできる。開発の世界は本当にクレイジーな時代だよ。他の人のベストプラクティスを見るのはいつも興味深い。

パターンベースのテストは理論的にはトークンコストを減らせるのかな?

TDDを使うと、重い税金がかかって速度が遅くなる。でも、コードは良くなるよ。

最近まで、自分のエージェントワークフローにTDDの赤-緑-リファクタリング手法を組み込むことを大いに支持してたけど、この研究を読んで同じことに気づいた。https://arxiv.org/pdf/2602.07900 TL;DR; テストを書く量は成功とは弱く相関していて、テストを書く原則を組み込んでも解決率は変わらなかったが、コストには実質的な変化があった。テストを奨励すると出力トークンが+19.8%増えても効果は0%; テストを discourage すると入力トークンが33〜49%節約されても精度が≤2.6pp落ちた。別に、TDD手順を強制することは逆効果になるようだ: 実際にリグレッションが6.08%から9.94%に増えた。私の意見では、テストが明らかに役立つのは主に生成後に適用される「オラクル」としてだと思う。それはモデルに信号を与えて、必要に応じて検証と自己修正を可能にする。

トークンコストが膨れ上がるってどういうこと!?テストを書くと、余分な関数が一つ増えるだけだし、機能ごとに段落が一つくらい(「赤いテストを作った」…「緑にした」)で、普通の開発とTDDの間で他は同じなんだよ。開発全体、特に思考トークンに比べたら、これは小さな話だよ。

私のアプローチ(特にLLMに関して)は、「Growing OO Software Guided by Tests」に書かれていることともっと一致してる。そこにある第4章では「まず、ウォーキングスケルトンをテストせよ」と言っていて、第5章には「各機能は受け入れテストから始めよ」とある。結局、まずは検証可能な方法でエンドツーエンドで何かを動かして、それから機能とそのテストをどんどん洗練させていく(できればTDDで)。LLMは一度に複数のテストケースを生成する傾向があることに気づいたけど(これは人間がTDDを進める方法じゃない)、指示しない限り統合テストから始めることはないんだよね。

これらの投稿は、実際の結果の比較が欠けてるね。「あなたはxをすべきだ」と逆のことを毎日読んでるよ。もしTDDが本当に良いなら、すでにシステムのプロンプトに入ってるはずだよ。

同意する - これらすべては雰囲気に基づいている(私も雰囲気でTDDを使ってるから、参考までに)。「TDD / 原始人 / [ランダムなスキルを挿入] は役に立つのか?」を決める唯一の方法は、自分のリポジトリから実際のPRを再生して品質を測ることだね。

これを試したことはないけど、最近Matt Pocockのスキルの大ファンになった。ワークフロー: /grill-with-docs -> /to-prd -> /to-issue -> /tdd。これは「共通理解」が得られるまで徹底的にインタビューして、「ユビキタス言語」を使って、ユーザーストーリーで要件を仕様化し、問題を作成してTDDを使って実装する。

最近、彼のスキルをすごく使ってるけど、素晴らしいよ。仕様スキルに技術的な計画を現在のコードベースに対して根付かせる問題を追加したし、仕様に関する問題のためにインターネットでベストプラクティスを調べるエージェントをたくさん生み出すリサーチスコールも作った。これで本当に物事がうまくいく。これら二つのために、彼のプロジェクトにPRを出さなきゃ…

彼はBMADメソッドからスキルを得たみたいだね。https://docs.bmad-method.org/tutorials/getting-started/

今日は学びました。ありがとう!

余談だけど、Jasonのポッドキャスト(codewithjason.com)をチェックしてみて。結構いいよ。最新のは「アンクルボブ・マーチン」との対談で、AIを使ったコーディングについて面白い見解を持ってる…古い人って言ってもいいかな?

ありがとう、気に入ってもらえて嬉しいよ!

コーデックスで直面した問題の一つは、フォールバックルーチンの使いすぎだね。プロのプログラミングでは多くの場面で良いプラクティスかもしれないけど、私の場合(このケースでは):測地線距離の計算と分析において、静かな悪いフォールバックは処理されたデータが思っていたものと違うってことになる。例えば、正確な方法の代わりに不正確な測地線メソッドを使ってしまったり。

これが大嫌いなんだ。私はこれを投機的コーディングって呼んでる。クロードはよく「防御的」プログラミングって言うけど、これが私のLLMに対する最大の不満だね。これを止めるための信頼できる方法はまだ見つけられてない。

この指定-エンコード-実行ループ/メソッドは、エージェントがバグのないコードを作成するのに効果的だよ。私のワークフローでは、まず自分で仕様を指定して、その後はLLMに任せてる。これで 1.) 理解度や仕様が確実に良い 2.) 実行可能なフォーマットに変換されるから、実装が検証できる 3.) 実装には最大限のコードカバレッジテストがあって、AIが基準に従ったコードを生成しやすく、既存のコードベースにもフィットして、リファクタリングも簡単になる。今のところ、これが私のソフトウェアエンジニアリングの実践におけるLLMの唯一の利点だね。人間が書いた仕様とコードを自信を持ってすぐに結びつけてくれる。

これらのLLMシステムが膨大なトレーニングセットと組み込みのシステムプロンプトを持っているのに、数段落の追加プロンプトで出力が意味のある形で修正されるとは信じがたいけど、こういう簡潔で集中したドキュメントを人々が書いているのを見るのは面白いね。若い開発者としてはこれがあれば良かったし、過去に働いていたチームにも役立ったと思う。私は自動化のためにちょこちょこPythonを触っていて、ここで__mharison__のスキルを読んで新しいことを学んだばかり。こういう知恵は昔はブログや先輩開発者の話の中にあったけど、こんなに簡潔に書かれたことはなかった。何十億ドルもかけて、ガイダンスが必要な人間のアナログに近いマシンを作る必要があったのがちょっと面白いね。

これが機能する理由は、モデルが何かを知っていることと、エージェントが何かを実行することには違いがあるからだよ。Claudeは、短い関数の方が理解しやすいことを「知っている」のに、巨大な未テストの関数を書いてしまうし、テストが安全なリファクタリングを可能にすることも「知っている」。モデルは、テストが賢いことと、テストが時間の無駄であることなど、矛盾する「事実」をたくさん「知っている」。両方の信念に同時に基づいて行動することはできないんだ。だから、自分の好ましい行動に向けて少し押し込むとうまくいくんだよ。

TDDは今のところ無駄な膨張だよ。まずはCodexを使って隙間を埋めて、それから一発で実装できるようにしよう。必要なら後でレビューすればいいし。これらのmdファイルは、モデルが進化するにつれてどんどん役に立たなくなるよ。