JUnitの使いこなし方を学ぶ本「JUnitイン・アクション」

テスト駆動開発JUnitを使い始めた頃に読んだ本。手元の本は2004年5月発行の初版なので、もう6年(!)も前の本になる。JUnit自体は(やや乱暴な言い方かも知れないけど)Assertによる検証をシステマティックに行うものであり、特に難しいものではない。例えば、「1+1の演算結果」が「期待通りの値である2になるか?」を確認するというという基本的なサンプルがよく紹介されているし、使い方としてはこれに尽きると思う。

むしろ難しいのは、ソフトウェアの設計として「いかにテストしやすい形の構成にするか?」という点だろう。仕様書通りに組み上げたソフトウェアでは残念ながら粒度が荒すぎるし、テスト対象も広過ぎる。様々なしがらみが付いて回るので、検証のためにはダミーデータを準備しておく必要があるかも知れない。だから、コードの設計を少し変えて、検証しやすい形態にする方がずっと重要なのだ。これらの考え方を総称するものとして、テスト容易性(EoT=Ease of Testing)という言葉が使われることもある。(あまりメジャーではないけど)

JUnitイン・アクションでは、そのような方法論を「テスト戦略」として、スタブやモックオブジェクトによるテスト分離方法など様々な形で紹介している。一例として載っているのが、HTTP通信を行うJavaクライアントのテストだ。目標は「通信データのやり取りを如何に誤魔化して、実際の通信無しでテストするか」。全てクライアント側だけでテスト出来れば、正常系はもちろんのこと、サーバでエラーが起こった場合や通信エラーが発生した場合の異常系についても検証が可能になりメリットは大きい。

こんな場面に対処する案が幾つが紹介されている。

  • URLクラスを継承したMockURLを使い、任意のデータをクライアントへ返す案
    • 結果:URLクラスはfinalで定義されているので、継承させてMockURLなるクラスを作ることは出来ずボツ。
  • クラスを継承して、データを設定するためのsetterメソッドを追加しておき、オーバーライドしたgetterメソッドから任意のデータをクライアントへ返す案
    • 結果:悪くはない。但し、テストしているのは対象そのものではなく、継承した「似て非なるクラス」になってしまっているのが問題。
  • Inversion of Control(IoC)を使う案
    • 結果:「データ取得」を「接続方法」から独立させるというコロンブスの卵的な発想により、任意のデータを返すことが可能。しかも、HTTPに限らず任意のプロトコルに対してでもテスト可能。

この本で紹介されているテクニックを知るまでは、「サーバからエラーを返すように予め設定しておく」なんて言う小賢しい方法でテスト環境を準備してから実際のテストを行っていたのだが、そんな原始的な方法では準備が大変だし、頻繁に繰り返し検証するのも難しい。IoCパターンを使う方法なら、実際の通信を行わないのでサーバが不要であり、しかも正常系と異常系を含めたあらゆるテストがクライアントだけで可能だ。

本を読んだ当時、こんな上手いテスト方法が有ったのかと驚愕した記憶が有る。それ以来、このテクニックを様々な場面や環境に応用してテスト駆動開発を行ってきた。サーバの開発より先行して、あるいはエラー処理も含めた任意の動作を確実にテストできるので非常に有りがたい。知っている人にとっては「アタリマエ」の手法なのだけど、「通信を行わずに通信のテストを行う」ので知らない人は驚くことが多い。また、「何をやっているのか理解できない」というプログラマや、「そんなことはコーディングの枝葉末節に過ぎない」と論評する上から目線の人もいるのは残念。優れたコードの価値が分かる人にこそ習得して欲しい技術だと思う。

他にもサーブレットテストのCactusや、データベーステストのDbUnitなど現場で役立つテクニックが満載だ。日本語版書籍は残念ながら絶版となっているようだが、オリジナルの英語版は間もなく第2版が出てくるらしい。新しいテクニックがまた追加されているのか、今から刊行が待ち遠しい本だ。

JUnitイン・アクション

JUnitイン・アクション

JUnit in Action

JUnit in Action



関連