TDD の Death and Rebirth まごころを君に

我が輩のTDD体験を語る

背景

ここ最近のTDDに関する話の噛み合なさっぷりよ・・・

大きな疑問

業務でxUnit使ったテストファーストやってる人はいるの?

TDDは死んでないと言うても、業務でxUnit使ったテストファーストやってる人はいるの? じゃあ、自分はどうなのか?自分語りをする。

前提

ここで話すTDD

XPの第一版にはそれ以外の要素は書いてなかった。 俺はそう刷り込まれた。 一番大事だと思う要素から話す。

「これからインスピレーションを得たもっといい方法があるよ」って話は喜んで聞きます。

我が輩の経験

3プロジェクト

  1. C言語SDLパーサ
  2. C言語のOBEX通信モジュール
  3. C言語のツール

言語の性質は意図してません。たまたま経歴がそうだっただけです。

xUnitを使ったテストファーストの効用

よく言われる通りの効用がある

  • バグが減る
  • 設計が洗練される
  • 設計の練習になる

バグが減る

リリースまでに使う回数が増えるのでバグが減る。 手で動作確認するのに比べると100倍ぐらい多い回数実行できる。 たくさん実行すると、マルチスレッドのデッドロックを体験できることもある。

設計が洗練される

テストクラスはクライアントクラス以外のテスト対象クラスを使う視点になる。 簡易的な仕様変更になる。

下記の仕様に依存している暗黙の前提条件に気付くきっかけになる。

  • 呼び出し順
  • 初期値
  • 入力値の範囲

暗黙の前提条件を減らすと、他のプロジェクトに持って行きやすいポータブルなコードになる。

ただ、この効果は機能追加による現実の仕様変更に劣る。 テストコードは予想外の機能を追加しない。 なにより現実の仕様変更は実践的。

設計の練習になる

プログラミング初心者の設計の練習によい。

オブジェクト指向入門の4.3 機能的トップダウンアプローチに

機能的トップダウン設計を検討した結果. この手法は重要なソフトウェアシステムの開発には
不向きであることが明らかになった. 小規模のプログラムや独立したアルゴリズムについては
トップダウン設計はなお設計の模範として有用である. また, 系統的に問題を解決できるので, 
初級プログラミングコースの教育法として役に立つことも確かである.

そして

トップダウン法では全てのシステムが最も抽象的なレベルでその第1の機能を記述できるもの
とされている. (中略)現実のシステムには頂点など存在しない。

ともある。

TDDでは

  1. テストコードで第1の機能を指定できる
  2. 機能的トップダウンアプローチが可能
  3. 系統的に問題を解決できる
  4. プログラミング初級者でも処理の設計がしやすい

この性質を利用してTDDの三角測量がなりたつ。

そしてレッド/グリーン/リファクタリングの黄金の回転をまわしながらオブジェクトを見つけ出す。 オブジェクト指向に至る。

ただし、この手法だけでデザインパターンを活用するオブジェクト指向設計にたどりつくのは困難。 慣れてきたらオブジェクト指向のこころを読もう。

これは個人の経験に基づく感想であり、効果を保証するものではありません。

xUnitを使ったテストファーストの前提条件

第1の機能がないと始められない。

事前の設計が必要。 ERモデリングだけでは不十分。 C言語ならモジュール構成。 OO言語なら、クラス単位まで行かないクラス群単位のおおざっぱなオブジェクト構成が必要。 最低限インタフェース数と入出力の論理名ぐらいが必要。

三角測量と逆向きになるのでTDD BootCampから実案件への移行には苦労するのではないかと思う。

もうやってない

もう6年やってない。

予算1000万の業務用WEBアプリの場合、オブジェクトの構成が決まらない。 レイヤーはプレゼンテーション、サービス、DAOぐらいで決まる。 しかし、オブジェクト単位の仕様は画面仕様依存でインタフェースが決まらない。

仮に事前に設計してテストコードを書いても、 画面を見せながら仕様検討・変更する。 機能が変わるとテストコードの修正も必要になり手間が増える。

画面の機能から作り始めるとユニットテストを書くマインドに切り替えるコストが高すぎる。 それよりユーザのマインドに切り替えた方が以下の良い気付きが得られる。

  • この画面は必要か?
  • 画面のレイアウトから機能が読み取りやすいか?
  • 画面を複数に分けた方がよいか?

画面の機能が8割固まるまでは手で回帰テストをしている。 この時はどの機能がどのプロダクトコードに依存しているか把握できている。 どの機能を動かして確認すればよいかわかっている。

xUnitを使った「後追い自動テスト」はやってる

ある程度機能が固まってから後追いでテストコードを書くことはある。

数年前に作ったライブラリに機能追加するときはテストコードがあるととても心強い。 例えば Alhambra というライブラリのテストはMSTestで書いている。

ライブラリをメンテナンスしたい時は、ライブラリのメンテナンスをしたいのではなくライブラリを使用しているプログラムを修正したい。 ライブラリの修正や動作確認に時間を使いたくない。 自動テストがあれば2年ぶりの機能追加でも、テストを実行するだけで既存機能を壊してないとわかる。

ただし、これはxUnitでEnd-to-Endの自動回帰テストを書いている。 ユニットテストとしては悪いと言われているDBに依存したテスト。

これは上記ライブラリの使用を推奨するものではありません。 EntityFrameworkでもLINQtoSQLでも好きなものを使ってください。

自動回帰テスト

作れるならEnd-to-Endの機能テストを自動化した方がうれしい。 テストコードが無駄にならずに内部構成を修正できる。

xUnitレベルのテストではレイヤーの追加・削除やデザインパターンの適用などで オブジェクトの構成を変更すると、かなりのテストコードを捨てることになる。

結論

「xUnit使ったテストファースト」は死んだ。

あとは知らん

参考文献

XPエクストリーム・プログラミング入門―ソフトウェア開発の究極の手法オブジェクト指向入門オブジェクト指向のこころ