「テスト駆動開発」を読んだ違和感
私は社内でテスト駆動を布教してしまう程度には、テスト駆動が好きです。そのため、ことあるごとに色んな人にテスト駆動開発の本を勧めているのですが、テスト駆動開発には独特の読みにくさがあります。
その"読みにくさ"というのは、どういうことなのか?KentBeckのテスト駆動開発は、3部から構成されています。
- 第1部 多国通貨
- 第2部 xUnit
- 第3部 テスト駆動開発のパターン
第1部の「多国通貨」はテスト駆動の入門の章です。ドルやフランなど複数の通貨単位を相互に変換したり、足し算や、掛け算を行うロジックを、テストファーストで構築していきます。
第2部の「xUnit」は、その名の通り、xUnit自身をテスト駆動開発で作っていきます。少し文章で表現するのが難しい内容ですが、例えば、pythonには標準でunittestというテストのフレームワークが存在します。このxUnitの章では、このunittest自身をテスト駆動で作ってしまおう。という内容です。
第3部の「テスト駆動開発のパターン」は、知識やHowToに近い内容です。第1部、第2部が実践としてテスト駆動を行うのに対し、第3部は「テスト駆動の実行の仕方」のような、少し抽象度の高い内容であったり、テスト駆動で頻出するデザインパターンやリファクタリングについて説明されています。
ある日、テスト駆動を布教した人に話を聞いたところ、 「第2部のxUnitが読みにくかった」 という感想をもらいました。これは、非常に同感でした。確かに、最初の多国通貨の例は人工的ではありつつも、入門としては複雑すぎず、かといって簡単すぎず、テスト駆動で動作を保証しながら学ぶにはよい題材であったと感じました。しかし、一方で、xUnitに関して言うと、なぜこれを題材にしたのか?は、疑問が残る内容でした。1つには、必要性を感じないことです。そもそも、現代において、unittestなどのテストフレームワークに関して、豊富にある中で、わざわざ取り上げるべき題材ではないように思いました。また、コード自体もリフレクションを用いたコードであり、入門書で取り扱うには技巧的な印象を受けます。そして、コード自体が自己言及的な入れ子の構造を持つため、注意深く集中して読む必要があり、読みやすい部類では無いです。では、なぜKentBeckは第2部で読みにくいxUnitをテスト駆動の題材として選んだのでしょうか?
xUnitの歴史
JUnitに代表されるようなテストフレームワークをxUnitと呼びます。xUnit系のテストフレームワークは、ほぼすべてのプログラミング言語に実装されていると言っても過言ではないです。私が触ったことがあるものでも、JavaにおけるJUnitは言わずもがな、PHPではphpunit、C#ではNUnit、C++ではcppunitなどがあります。では、xUnitの一番最初の実装は何でしょう?
xUnitの一番最初の実装はKentBeckがSmalltalk用に作ったSUnit
です。xUnitのWikipediaによると、
このようなフレームワークの最初の実装は、ケント・ベックが開発したSmalltalk用のテスティングフレームワークSUnitである。その後、各コンピュータプログラム言語や開発環境毎に、同様の設計を持つフレームワークが多数作成されている。xUnitそれ自体は非常に単純なプログラムであるが、近年のソフトウェア開発で採用されつつある。JUnit(Java用のxUnit)の項目も参照。
とあります。SUnitのWikipediaを見に行くと
SUnitはケント・ベックの著書「Kent Beck's Guide to Better Smalltalk」の第30章「Simple Smalltalk Testing」および「Simple Smalltalk Testing:With Patterns[注釈 2]」(1989)にて発表された。
とあります。そう xUnit自体もKentBeckが1989年に構築したソフトウェア だったのです。
実は、Java用のxUnitであるJUnitの誕生には逸話があります。リファクタリングで有名なマーチン・ファウラーのXUnitにこういった記述があります。
JUnitは、1997年にアトランタで開かれたOOPSLAに向かうチューリッヒ発の飛行機のなかで産声を上げた。 KentはErich Gammaと一緒だったが、2人のギークが長時間のフライトでやることといったら、それはプログラムしかないでしょう。 JUnitの最初のバージョンは、そこで、ペアプログラミングで、テストファーストで作られた(メタ循環的なのがギークっぽくてよいね)。
そう。実は、JUnitはKentとEric Gamma(デザインパターンで有名なGang of Fourの1人)が飛行機の中でペアプロで作ったものがベースとなっています。
KentBeckはテスト駆動というプラクティス行うために、xUnitという概念が必要だったのです。
第2部「xUnit」の本懐
これはあくまで私自身の見解で、実は違った。ということは大いにあり得るので、予防線を張らしていただきたいです。
元祖のxUnitであるSUnitはSmalltalkの実装で、1989年に公開された。
1991年、世界で初めてWebページが公開された。
その後、KentBeckとErich Gammaは1997年にペアプロでJUnitのプロトタイプを作成した。
Wikipediaによると、Test-Driven Development: By Example.の出版年は2002年だった。
テスト駆動をするためには、テストを実行するためのテストフレームワークが必要であった。
しかし、時代の問題でプログラミング言語によってはテストフレームワーク自身が存在しない場合が存在した。(SVNの登場が2000年、Gitの登場が2005年のため、今ほどコードの再利用性が高くはないと考えられる)
テストフレームワークが無いと、テスト駆動が出来ない。
この鶏卵問題を解決するためにはどうすればよいか?
テスト駆動開発の書籍の1つの章として、テストフレームワーク自身をテスト駆動で開発する構成にした。
ということではないだろうか。
確かに、現代的な観点からすると、ほとんどの言語にxUnitが存在する。そういう意味では、入門にしては無駄に難易度が高いxUnitの章は、「好事家の遊び」の風情がある。しかし、テスト駆動が書かれた当時は、テストフレームワーク自体が無い状態もありえた。そう考えた場合、テスト駆動のために、テストフレームワーク自体を自作せざるを得なかった。そのための、xUnitの章であった。
こう考えると、私としては、とても納得のいく書籍の構成であった。
感想
テスト駆動は何度となく読んだり、写経をしたりしていました。しかし、言語によっては第2部のxUnitは組みにくかったり、そもそもリフレクションが使いにくい静的型の言語では、普通になぞるだけでは使えない。ということも多々ありました。そのため、なぜこんな章があるのか?というところは疑問に思っていました。
そんななかで、ネットで探し物をしているうちに以下のツイートを見つけました。
Kent Beckにはテスト自動化とSmalltalkの知識があり、Javaを知りたかった
— Takuto Wada (@t_wada) March 20, 2019
Erich Gamma(GoFのひとり)にはデザインパターンとJavaの知識があり、テスト自動化を知りたかった
その2人がチューリッヒからOOPSLA97開催地のアトランタに向かう飛行機で隣同士の席を取り、ペアプロして生まれたのがJUnitです https://t.co/FRBcYZkChs
えー!?JUnit作ったのもKentBeckなの?という驚きとともに、待って。そもそもxUnitの始祖もKentBeckじゃない!?と気づいて書いたのがこの記事になります。
そもそも現代の自分たちは、「xUnitがある世界」が普通だと感じているために、なんでこんなめんどくさいものを実装させるんだ?と思ってしまいますが、テスト駆動開発の執筆当時は「xUnitが無い世界」が普通であると考えると、そうか。だから、xUnitの章があるんだ。と、非常にスッキリしました。
「xUnit」の章は、KentBeckとErich Gammaのペアプロの"リプレイ"を、書面を通じて現代で見ている。ともいえるかもしれません。