テストを“いちばん重要な財産”と考えると見えるもの

第2回 本当にコードを失っても大丈夫なのか,確かめてみよう

この記事を読むのに必要な時間:およそ 8 分

テスト駆動開発はなぜ直感に反することをするのか

ここまでの流れで,テスト駆動開発の感じをつかんでいただけたと思うのですが,いかがでしたでしょうか。明らかに直感に反するところがあると感じられたのではないでしょうか。そこで,直感に反する部分について,分析してみることにしましょう。

まず「最初は,テストを通すだけのシンプルなコードを書く」です。これまで,最初に書いたコードは,どれも役に立たないインチキなコードでした。これには意味があるのでしょうか。

1つ利点として言えるのは,書いたコードは必ずテストされる,ということです。もし,最初から長いコードを書いてしまうと,対応するテストを書き忘れてしまうかもしれません。今回のやり方では,テストを通すのに必要な最低限のコードしか書きませんでした。ですからどのコードも,いずれかのテストに必要だから書かれた,ということが確信できます。

ほかにも,テストは一度に1つだけ書く,というのも納得がいかないかもしれません。同じ種類の仕事をまとめてやった方がはかどる,という方もいらっしゃるでしょう。これも,今の(インチキな)コードを改善するのに必要なテストだけを書くことで,コードをまとめて書かないようにするしかけと捉えることができます。

これらのやり方は,最初に書いた「万一コードをすべて失ったとしても,テストが無事なら元と同じ品質のコードをもう一度書くことができる」にも貢献します。せっかくですから,いま書いたテストを見て確認してみましょう。

                $obj =& new testrail();
                asserteq("00", $obj->number);
                $obj =& new testrail("12");
                asserteq("12", $obj->number);

最初の2つのテストは,コンストラクタをテストしています。渡されたパラメータがnumberというメンバ変数に格納され,省略時は"00"であることが,テストからわかります。

                $obj->gethttp("http://a.b/");
                asserteq("http://a.b/", $obj->gethttpurl);

次はgethttp()ですが,これは以下のモックを見れば,わかります。

        var     $gethttpurl;
        function        testrail($number = "00") {
                parent::rail($number);
                $this->baseurl = "http://a.b/";
        }
        function        gethttp($url) {
                $this->gethttpurl = $url;
        }

テスト用に"http://a.b/"を用意していることがわかりますし,通常実行のときは,ユーザが設定したURLになることが想像できます。

                $obj =& new testrail("34");
                $obj->drive();
                asserteq("http://a.b/?34=A", $obj->gethttpurl);

drive()メソッドも,今までの知識から,簡単にコードを復元することができます。

つまり,小さなテストを書いて,それを通すだけのコードを書く,という繰り返しにより,コードを書くのに必要な情報がすべてテストに書かれている状態になった,というわけです。

テスト駆動開発に向かないもの

冒頭に「なぜリスト1をテスト駆動にしようと思わないかの分析は後半で行う」と書きました。最後にこれをやってみましょう。

筆者は,テストが必要な場面は3つあると思っています。

1つめは「間違えたまま,すぐには見つからない可能性があるもの」です。前回のmakebooklet()などは,書いて一度動かしただけでは心配がありますから,いくつかのケースでテストしたくなります。独自のソートアルゴリズムを書いた場合なども同様ですね。

2つめは「将来,保守されるもの」です。保守の場合,たとえば機能追加されたときに今までの部分の動作が変わっていないかとか,あるいは別のところが変わったために呼び出し方法を変えたいが問題ないか,といった不安が出てきます。テストがあると,こういった不安を減らすことができます。また,テストが通っている限り,テストとコードは一致していると考えられますが,これはコメントにはない長所です。

3つめは「再利用されるもの」です。コードだけがいろいろなものに再利用されると,年月を経たときに何が正しい動作なのがわからなくなることがあります。このときにテストがあると,バージョンごとの意図などを読み取ることができます。

リスト1の場合,あいにくどれにも当てはまりません。やっていることは明確で,間違いがあったら実行したときにすぐに気付くと考えられます。それに,保守することを考えたら,むしろテストは保守を困難にする可能性があります。再利用も,ちょっと考えられません。

テストの保守性については,別の視点もありますので,次回で取り上げたいと思います。ぜひ楽しみにしてください。

著者プロフィール

木元峰之(きもとみねゆき)

独立系ソフトハウスに8年間勤務,パッケージソフトの開発や記事執筆などを行う。現在はフリーのコンサルタント。SWESTなどのワークショップで分科会のコーディネータを務める。デジタル回路設計歴30年,プログラミング歴27年。

きもと特急電子設計
URL:http://business.pa-i.org/