ソフトウェアテストの系譜 — デバッグから AI 時代まで、 「正しさ」を問う70年
1940年代の「バグ第一号」の逸話から、 xUnit の誕生、 TDD/BDD の興隆、 モックとプロパティベーステスト、 E2E の世代交代、 カバレッジとミューテーション、 フレーキーテストとの戦い、 そして生成AIがテストの書き方を変えつつある現在まで。 「プログラムが正しいことをどう確かめるか」「テストで何を保証でき、 何を保証できないか」という問いが時代ごとにどう作り変えられてきたかを辿る、 全18話のシリーズ地図。
ソフトウェアテストに「歴史」はあるのか
ある。 しかも、 70年余りの。 そして重要なのは、 ソフトウェアテストは一枚岩の「正しいやり方」ではなく、 時代ごとに根本から作り変えられてきたということだ。 1960年代のプログラマが考えていた「テスト」と、 2000年代の TDD 実践者が考えていた「テスト」と、 2020年代に AI とペアを組む開発者が考える「テスト」は、 前提そのものが違う。
本シリーズは、 姉妹シリーズ [数学の系譜]・[音楽理論の系譜] が「問いと答えの変遷」として学問の歴史を辿ったのと同じように、 ソフトウェアテストを 考え方の歴史 として辿る。 中心にある問いはシンプルで、 しかもいまだに決着していない。
プログラムが正しいことを、 どうやって確かめるのか。 そしてテストは、 何を保証でき、 何を保証できないのか。
この二つの問いへの答えは、 手作業のデバッグから、 自動化されたフレームワークへ、 さらに生成AIへと、 70年をかけて何度も書き換えられてきた。 本シリーズは、 その書き換えの歴史を辿る。
通底する4つの糸
70年を貫く対立・課題が4つある。 どの時代の話も、 この4本のどれかに触れている。
- 検証 vs 妥当性確認 — 「仕様通りに正しく作れているか(Verification)」と「そもそも正しいものを作っているか(Validation)」。 テストはほぼ検証の領域にとどまり続け、 妥当性確認とは別問題であり続ける
- 手動から自動化、 そしてAIへ — 誰が、 何がテストを書き実行するのか。 手作業のカード照合から xUnit フレームワークへ、 CI 上の自動実行へ、 さらに AI による叩き台生成へと、 主体そのものが移り変わってきた
- どこで確かめるか — 単体・統合・E2E のどこに比重を置くか。 テストピラミッド・トロフィー・ハニカム、 そしてアイスクリームコーン(アンチパターン)という戦略モデルの対立
- 網羅性の限界 — Dijkstra の警句「テストはバグの存在を示せるが、 不在は示せない」が突きつけた原理的限界。 形式手法はこの限界を数学的に埋めようとする、 もう一つの道である
ひとことで振り返る70年
年表を先に一望しておく。 細部は各話に譲り、 ここでは「時代ごとに何が起きたか」を一行で掴んでおきたい。
| 年代 | ひとことで言うと |
|---|---|
| 〜1970年代 | 手動確認とデバッグの延長。 テストはまだ独立した工程ではなかった |
| 1990年代半ば | SUnit が xUnit 系の原型パターン(fixture・テストランナーなど)を確立する |
| 1997〜2002年 | JUnit の普及と TDD の体系化により、 テストが「設計を導く行為」になる |
| 2000年代後半 | BDD・Cucumber・『xUnit Test Patterns』でテストの語彙と手法が結晶化する |
| 2010年代前半 | フロントエンド向けフレームワーク(Jasmine → Jest)が爆発的に普及する |
| 2010年代後半 | Selenium 一強から Cypress・Puppeteer へ、 E2E ツールの世代交代が進む |
| 2020年代 | Playwright によるマルチブラウザ統一と、 LLM によるテスト生成の浸透が進む |
70年の5つの時代 — 全18話の地図
以下、 全18話(overview を除く)を5つの Part に分けて紹介する。
Part I: 前史と自動化の夜明け(第1〜3話)
まだ「テスト」が独立した工程ではなかった時代から、 xUnit という共通言語が世界に広がるまでを辿る。
| 話 | タイトル | 内容 |
|---|---|---|
| 第1話 | 前史 — デバッグからテストへ | デバッグとテストが未分化だった1950年代、 ソフトウェア危機、 Dijkstra の警句、 Myers『The Art of Software Testing』(1979) |
| 第2話 | xUnitの誕生 | Kent Beck の SUnit(Smalltalk)、 飛行機の中で書かれたという JUnit の逸話、 TestCase・assert・fixture という共通語彙の確立 |
| 第3話 | xUnitの世界展開 | JUnit の設計思想が C++・.NET・Python・Ruby・PHP など各言語へ移植されていく過程 |
Part II: 思想の興隆(第4〜7話)
テストが「バグ探し」から「設計を導く行為」へと意味を変えていった、 思想的な転換の時代。
| 話 | タイトル | 内容 |
|---|---|---|
| 第4話 | TDDの興隆と論争 | Kent Beck『Test-Driven Development: By Example』(2002)、 Red-Green-Refactor、 「TDD is dead」論争 |
| 第5話 | BDDへ | Dan North が提唱した BDD、 Gherkin と Cucumber、 「テスト」を「振る舞い」の言葉に置き換える発想 |
| 第6話 | モックの物語 | モックオブジェクトの理論化、 ロンドン学派とデトロイト学派/古典派の対立 |
| 第7話 | プロパティベーステスト | QuickCheck、 Hypothesis — 「個別の例」ではなく「性質」を書くという発想の転換 |
Part III: 現場の壁を越えて(第8〜10話)
ブラウザとフロントエンドという新しい戦場で、 テストがどう進化したかを辿る。
| 話 | タイトル | 内容 |
|---|---|---|
| 第8話 | E2Eの世代交代 | Selenium → Cypress → Playwright、 ブラウザ自動化ツールの世代交代 |
| 第9話 | JavaScriptテストの進化 | Jasmine → Jest、 フロントエンド固有のテスト文化の発展 |
| 第10話 | 言語別エコシステムの現在地 | Java/Kotlin・Python・Ruby・Rust・Go など、 各言語の現在の標準ツール |
Part IV: 設計と技法(第11〜13話)
「良いテストとは何か」を技法として掘り下げる時代。
| 話 | タイトル | 内容 |
|---|---|---|
| 第11話 | テストの形 | テストピラミッド・トロフィー・ハニカム、 戦略モデルの使い分け |
| 第12話 | 単体テストの設計と契約 | 良い単体テストの設計原則、 契約テストによる結合コストの低減 |
| 第13話 | カバレッジとミューテーション | カバレッジ指標の理論と限界、 ミューテーションテストによる「テストの強さ」の計測 |
Part V: 現代の実践と限界(第14〜18話)
組織・規模・AI という現代的な変数のなかで、 テストはどこへ向かうのかを辿る。
| 話 | タイトル | 内容 |
|---|---|---|
| 第14話 | フレーキーテストとの戦い | 不安定なテストが組織の信頼を蝕む仕組みと、 検出・隔離・根絶のサイクル |
| 第15話 | テストの限界と形式手法 | Dijkstra の警句を数学的に埋めようとする形式検証・モデル検査との関係 |
| 第16話 | 品質を全員で | QA という職能の歴史的変遷、 「品質は全員の責任」という現代的な考え方 |
| 第17話 | 大規模開発のテスト | モノレポ・大規模組織におけるテスト運用の現実的な課題 |
| 第18話 | AI時代のテスト | LLM によるテスト生成の可能性と罠、 「AI が書いたテストをどう信頼するか」という新しい問い |
「バグを見つける」から「変更を可能にする」へ
テストの目的観そのものも、 70年のあいだに何度も塗り替えられてきた。 1970年代末、 Myers はテストを「誤りを見つける意図を持ってプログラムを実行するプロセス」と定義し、 破壊的な行為として位置づけた。 1990年代、 Kent Beck が TDD を体系化すると、 テストは「書いたコードを確認するもの」から「実装の設計を導くもの」へと意味を変える。 2000年代以降、 継続的デリバリの普及とともに、 テストは個々の開発者の安全網を超え、 「組織が本番環境に安全に変更を届けるための社会的インフラ」という役割を担うようになった。
この意味の変遷を追うことは、 単なる技術年表を眺めること以上の意味を持つ。 それぞれの時代がテストに何を期待していたかを知ることは、 なぜ今のプラクティス — TDD、 CI、 カバレッジ目標、 契約テストなど — がこの形になっているのかを理解する近道になる。 逆に言えば、 今「当たり前」とされているテストの作法も、 いずれ別の前提のもとで作り変えられていく途中の一形態にすぎない。
テストは何を保証し、 何を保証しないのか
本シリーズを通じて繰り返し立ち返る境界線がもう一つある。 テストが緑(パス)であることは、 「試した範囲で誤りが見つからなかった」ことしか意味しない。 Dijkstra が指摘したように、 テストは無限に近い入力の中から有限個を選んで実行する行為である以上、 原理的に「バグが一つも存在しない」ことまでは証明できない。 この限界を数学的に埋めようとするのが形式手法(第15話)であり、 一方でこの限界を受け入れた上で「実務上どこまでのリスクなら許容できるか」を判断し続けるのが、 現代のテスト戦略(第11〜13話、 第17話)である。 テストの歴史は、 この「保証できることと、 できないこと」の境界線を、 各時代がどう引き直してきたかの記録でもある。
姉妹シリーズとの関係
本シリーズは、 [数学の系譜]・[音楽理論の系譜] と同じ「考え方の歴史」を扱うシリーズである。 数学が「証明」という営みの歴史であり、 音楽理論が「協和・不協和をどう捉えるか」の歴史であるように、 ソフトウェアテストは「プログラムの正しさをどう確かめるか」という問いの歴史である。 三つのシリーズに共通するのは、 「今のやり方は最初からそうだったわけではなく、 論争と試行錯誤の末にたどり着いた一つの到達点にすぎない」という視点だ。
想定する読者
本シリーズは、 次のような読者を念頭に置いている。
- TDD・BDD・モック・プロパティベーステストといった用語を見聞きしたことはあるが、 由来や論争の経緯までは知らない人
- チームのテスト戦略(ピラミッド構成、 カバレッジ目標、 フレーキー対策など)を、 歴史的背景とともに見直したい実務者
- 「なぜ今のテストプラクティスがこの形になっているのか」を、 断片的な Tips の寄せ集めではなく、 歴史の積み重ねとして理解したい人
この先の読み方
通史として第1話から順に読めば、 1950年代の未分化な「デバッグ」から2020年代の AI 活用まで、 一本の流れとして追うことができる。 個別の技法(モック、 プロパティベース、 カバレッジなど)に興味があれば、 該当する話だけをつまみ食いしてもよい。 年号や人物の細部よりも、 「なぜその時代にその考え方が生まれ、 何と対立し、 何を残したか」という因果の連なりを追うことを、 本シリーズは重視する。
次の第1話では、 まだ「テスト」という言葉が独立した意味を持っていなかった時代 — デバッグとテストが未分化だった1950年代 — から物語を始める。
公開済みの記事
- 前史 — デバッグからテストへ、体系化前夜の30年
- xUnitの誕生 — SUnitからJUnitへ、伝説の機内ペアプロ
- xUnitファミリーの世界展開 — JUnitから広がった移植の波
- TDDの興隆と論争 — XPの一プラクティスから独立した技法へ
- BDDへ — 「振る舞い」に着目したテストの語彙革命
- モックの物語 — Endo-TestingからMockitoまで
- プロパティベーステストの系譜 — QuickCheckからHypothesisまで
- E2Eの世代交代 — SeleniumからPlaywrightまで
- JavaScriptテストの進化 — JasmineからVitestへ
- 言語別エコシステムの現在地 — pytest・RSpec・JUnit・Goのtesting
- テストの形 — ピラミッド・アイスクリームコーン・トロフィー・ハニカム
- 良い単体テストとは何か — FIRST原則から契約テストまで
- テストの質をどう測るか — カバレッジとミューテーションテスト
- フレーキーテストとの戦い — 信頼できないテストが信頼を蝕む
- テストの限界と形式手法 — 「不在」を証明するもう一つの道
- 品質は誰の仕事か — 専任テスターから全員品質へ
- 大規模開発のテスト — 数百万件のテストと、 それを支える設計
- AI時代のテスト — 変わった実態と、 変わらない問い