自信を持ってTDDするために – 読書 – 実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる

TDDについて少し勉強し、実際に使ってみたはいいものの、次々と現れる疑問や不安。「ほんとにこの方法でいいんだろうか」を気持ちを払拭するために、そして、より深くTDDについて理解するために、本書を手にとって読んでみました。

実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)
実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる

目次

  • 第I部 導入
    • 第1章 テスト駆動開発のポイントとは?
    • 第2章 オブジェクトをテスト駆動開発する
    • 第3章 ツールの紹介
  • 第II部 テスト駆動開発のプロセス
    • 第4章 テスト駆動のサイクルに火を入れる
    • 第5章 テスト駆動のサイクルを保つ
    • 第6章 オブジェクト指向スタイル
    • 第7章 オブジェクト指向設計を実現する
    • 第8章 サードパーティコードの上に構築する
  • 第III部 動くサンプル
    • 第9章 オークションスナイパーを作動させる
    • 第10章 動くスケルトン
    • 第11章 最初のテストを通す
    • 第12章 入札を準備する
    • 第13章 スナイパーが入札する
    • 第14章 スナイパーがオークションで落札する
    • 第15章 実際のユーザインターフェイスに向けて
    • 第16章 複数の商品をスナイプする
    • 第17章 Mainクラスを分解する
    • 第18章 詳細を詰める
    • 第19章 エラー処理
  • 第IV部 持続可能なテスト駆動開発
    • 第20章 テストの声を聴く
    • 第21章 テストの可読性
    • 第22章 複雑なテストデータの構築
    • 第23章 テストの診断
    • 第24章 テストの柔軟性
  • 第V部 高度なトピック
    • 第25章 永続性のテスト
    • 第26章 ユニットテストとスレッド
    • 第27章 非同期処理のテスト
    • 第28章 ティム・マキノンによるモックオブジェクトの簡単な歴史

僕とテストコード

僕が初めてにテストコードを書いたのは、大体5〜6年前のこと。アルバイト先で先輩に「このクラスの単体テスト書いといて」と頼まれたのがきっかけでした。確か、言語はJavaで、使ったのはJUnitだったと記憶しています。

その頃はまだTDD(テスト駆動開発)という言葉や考え方を知りませんでした。僕のテストコードについての理解は、「ある特定の状況下でメソッドを呼び出した時に、期待する値を返してくれるかどうかを検証するもの」いう程度のものでした。

それからしばらく経って、TDDという言葉をWeb上の至るところで目にするようになりました。「これは勉強しなきゃな」と思い、The RSpec Bookの英語版を購入して、RSpecを使った単体テストや、Cucumberを使ったエンドツーエンドテストの書き方について学びました。

TDDの考え方や、テストフレームワークの使い方を覚えた僕は、早速Railsアプリの開発時にその方法を使うことにしました。最初の内はテストコードを書くこと自体を楽しんでいた記憶があります。でも、時間が経つうちにそういう気持ちは薄れ、色々な疑問が湧いてくるようになりました。

テストコードはどこまで詳細に書く必要があるんだろうか。スタブやモックオブジェクトは、どんな時に使えばいいんだろうか。エンドツーエンドテストを書くと、仕様変更や機能追加のコストが大きくならないだろうか。コストが大きくならないコツってあるんだろうか。他のプロジェクトではどんなテストを書いているんだろうか。そもそもTDDって何のためにやってるんだっけ。などなど。

疑問を抱えている状態では、なかなか自信をもってコードを書くことができません。そんな時、TDDに関して勉強したい人へのおすすめ本として紹介されていた本書に出会いました。

晴読雨読@エンジニアライフ: 実践テスト駆動開発――テストに導かれてオブジェクト指向ソフトウェアを育てる

TDDでソフトウェアを育てる

本書は、TDDの概念や目的、発生しがちなトラブルや、それらを解決するためのTipsについて、とても実践的な方法で解説しています。

サブタイトルにもあるように、TDDの目的は「オブジェクト指向ソフトウェアを育てる」ことです。開発中のソフトウェアの正しい現状を把握し、次にどの方向に進むかを決め、その方向に向かって着実に一歩進む。これをソフトウェアが完成するまでの間、細かくインクリメンタルに繰り返す。このようなソフトウェア開発プロセスを、本書では「育てる」と表現しています。

TDDでは、ソフトウェアの現在の状態が正しいかどうかを確認するために、テストコードを使います。その上で、次に満たすべきソフトウェアの状態を表すテストコードを追加し、テストの実行が失敗することを確認してから、それらが正常に実行できるように、プロダクションコードを実装していきます。これを何度も繰り返してソフトウェアを育てることこそが、TDDと呼ばれるプロセスです。

このようなことは、Web上の様々な記事や他の書籍にも書かれていることですし、僕自信も頭では理解しているつもりでした。ですが、本書では「オークションスナイパー」を開発する架空のソフトウェア開発プロジェクトのストーリーを通して、TDDのプロセスをより具体的に、実践的に解説してくれています。

オークションスナイパーの開発は、最初に「動くスケルトン」に対するエンドツーエンドテストを書くことから始まり、時には順調に、時には誤った選択をしながら、最終的なゴールである「完成」に向かって進みます。ソフトウェアを育てるということはどういうことなのか、インクリメンタルな開発プロセスにおいてテストコードはどのような役割を果たしてくれるのか、本書のストーリーを通して、今までよりもしっかりと理解することができました。

ただテストを書けばいいという訳ではない

本書には、「外側の質」「内側の質」という、ソフトウェアの品質に関する2つの言葉が登場します。

外側の質とは、ソフトウェアを利用する顧客から見たソフトウェアの品質のことです。顧客が求める価値をソフトウェアが正しく提供できているかどうかによって、質の良し悪しが決まります。外側の質はエンドツーエンドテストによって確保することができます。

対して、内側の質とは、ソフトウェアを開発する開発者から見たソフトウェアの品質のことです。ソフトウェア内部に適切なコンポーネントが存在し、それらが適切にコミュニケーションできているかどうかによって、質の良し悪しが決まります。内側の質が高いと、機能追加が容易で、保守性の高いソフトウェアになります。これらの質は主に単体テストによって確保されます。

ただし、ただテストを書けばいいという訳ではありません。テストを書いて満足していてはいけないということです。テストを適切に書かないと、内側の質の向上に何の役にも立たないばかりか、機能追加の足かせにしかならないことだってありえます。

テスト対象のオブジェクトの振る舞いを、テストコード自体が表現できているか。オブジェクトと他のオブジェクトとの関係を、モックオブジェクトを使って正しく記述できているか。テスト失敗時に出力されるエラーメッセージから、今ソフトウェアに発生している問題を的確に把握することができるか。

これらを満たす適切なテストを書けて、初めてそのテストが生きてきます。テストを書いただけで満足してはいけません。意味のあるテストコードにするためには、もう何歩も先に進まなければいけないということです。僕はテストを書いて少し満足していたところがあったので、考えを改める良いきっかけになりました。

扱っている言語とテストフレームワーク

本書が扱う言語はJava、テストフレームワークはJUnitJMockHamcrestになります。

僕自身、Javaの経験が少しあるのと、CucumberやRspecを使ってテストコードを書いたこともあるので、なんとか理解することができましたが、予備知識がなかったとすると少々難しく感じていたかもしれません。

扱っているテーマ自体はプログラム言語や環境に依存しないものなので、サンプルコードがわからない場合は適当に読み飛ばしてもいいかもしれません。一旦本書を読み終えてから、周辺知識についても学習し、もう一度本書を読み直すと、さらに内容を深く理解できそうです。

自信を持ってTDDしよう

本書を読んで、自分がぶつかっていたTDDに関する疑問や不安が取り除かれたような気がします。TDDの目的や、それを駆使したソフトウェアの育て方について把握することができたので、少なくても以前と比べたら自信を持ってTDDによるソフトウェア開発ができそうです。

もちろん、本書に書いてあることをそのまま適用することができないプロジェクトもあると思います。そのような場合でも、本書のプロセスや考え方を自分なりにカスタマイズし、何とかしてソフトウェアを正しい方向に育てたい、そう思わせてくれる素晴らしい本でした。

他のTDD本も読んでみたいな。オススメなどありましたら、コメントで是非教えてください。それでは以上です。どうも、ありがとうございました。