テストコードのリファクタリング
TDDBC 福岡2でのTDDの失敗ケースとは何かという質疑応答から。
テストコードにもリファクタリングが必要
- 昔はテストコードがメンテ対象であるという意識が薄かった
- 見てすぐ分かるテストコードがよいという考えからコピペコードが非常に多かった
- テストコードがたくさんあることによって動きが取りづらくなり、変更コストも上がる
- 素早く動きたいがためにTDDしているのにそんな皮肉な結果になってしまう
- たくさん書くのではなく必要十分書くことが大切
- 書き散らすと「テストケース爆発」を起こす
- テストコードもメンテし続けるためにリファクタリングして行く必要がある
テストコードもプロダクトコードと同じようにテストのGreenの状態が維持されていることで、既存のコードが壊れないことを保証しつつリファクタリングしていくことができる。
(ただしテストが無条件でオールグリーンになるみたいな酷い壊し方をしてしまう心配はあるなあ)
リファクタリング内容は重複の排除や分かりやすい名前への変更などが主だろうか。
テストコードの重複を排除する方法としては
- setupやteardown等の前後処理にまとめる
- 重複部分をメソッド切り出す
といったものが通常は考えられる。
メソッド切り出しはやり方を間違えるとテストの文脈を追うのが困難になって何をテストしてるんだか分かりづらくなるが、そうならないようにうまくやれば有効。
RSpecはテストコードをDRYにすることに関してはShared Exampleやsubject、let等の優れた仕組みを持っているので素晴らしい。
テストコードを捨てるタイミング
メンテナンス性を維持するために不要なテストコードを捨てるという選択もある。
- 例えば三角測量した後のコードの片方とかいらないので消したい
- どういうタイミングで消したらいいのか
- 大きい粒度のテストが小さな粒度のテストを内包している場合などがある
- テストケースごとのガバレッジの重なりを見て、かぶっているところがあれば捨てる
- 上位のテストが出来上がったらいったんテストを捨てて整理し直すという手も でもコストかかる
同じ話でCucumber等の結合テストでカバーしたらスローテスト(テストが増えすぎて実行に時間がかかりすぎるようになること)の兼ね合いもあってバッサリ捨ててしまうという話をRails勉強会@東京で聞いたことがある。
いざとなればバージョン管理があるので思い切って捨てられるね。
ただし勢い余って必要なテストまで消さないようにしないとだ。