第17回で、プロダクトコードの重複の話をしました。そこでは、DRY(Don't rpeart yourself)原則、コードの「重複は悪」という話をしました。
では、テストコードの重複はどうでしょうか? 今回はその点について議論してみたいと思います。
テスト対象、納品対象のコードは、コードの重複や機能の重複というのは、あってはならない、というか理想的には1行も重複がないという状態で書かれるべきですが、ではテストコードはどうなのかという話です。
テストコードの中の重複をどんどん排除してくと、たとえばテストのヘルパクラスをたくさん作ったりとか、テストクラスの継承がどんどん深くなるといった結果になり、そのテストが実際にどのように動いているのかを調べるために、いろんなテスト用クラスを行ったり来たりしなければならないというような状況が出てきてしまいます。
そのような状況に直面したときに、テストコードの重複は善か悪かというような議論が出てきます。
2つの指針
「テストコードの重複」は、一番最後のトピックとしてちょうどいいかなと思っています。そして意見は以下の二つ
「テストコードには重複があってもいい、テストコードはその部分だけ見ればある程度何をやってるかわかるコード、重複があってもいいから何をやってるかわかるノッペリとした書かれ方がいい」
という考え方と、
「テストコードもコードはコード、テストコードにもプロダクトコードと同様にDRY原則が満たされなければならない」
という意見に、だいたいやはり2種類に分かれるんですね。
故・石井勝(masarl)さんの考え
故・石井勝さんという方は、テストコードは重複があってもいいと、おっしゃっています[1]。テストは、そのテストコードのブロックだけ見れば、ある程度なにやってるかわかるという単純な書かれ方がよいという考え方です。
私自身もmasarlさんの考え方に沿っています。重複がいくつかあってもいいという考え方ですので、テストのメンテナンスをするときに何ヵ所かを同時にいじるという状況になってしまうことがあり得るんですけども、それでもテストは単純な書かれ方のほうがいいという考えです。
達人プログラマーDave ThomasとAndy Huntの考え
一方、『達人プログラマー』(注2)という本で有名なDave ThomasとAndy Huntは、『達人プログラマー』(アスキー刊のほう)の中で「テストコードも実コードである」ということを書いています。テストコードも実コードと同じ厳しい基準であたり、テストコードにも重複はあってはならないという意見です。
みなさんの意見
実際に迷うところだとは思うんですけども、先述したように私はテストコードの重複は「あり」で進めています。最後にここにいる方々の考えをお聞きしたいなと思います。
クロコさんの発言
私はありだと思います。テストを見て、そのテストだけでやってることがわからないと、どこを探していいのかわからなくなります。
MIZOさんの発言
私もありだと思っています。
ペアプロとかをやってる場合はもしかしたらいらないのかもしれないと思ったんですけども、要は突然、人のテストを見たときに、「何を書いてるのこのテストは?」って説明を求めるところから始めるよりは、わかるテストコードを見られることに魅力を感じてます。意図もわかるコードを見せてほしいと。
宮澤さんの発言
まあ、ありだとは思うんですけども、テストが増えていくと重複も増えていって、そこでやっぱりある程度整理が必要だと思うんですね。そこがちょっとまだ判断基準が難しい……。
私もまさしく同じようなことを考えていて、重複が非常に多くなってしまう場合に、ではその重複に意味があるのかないのか。
意味があるのであれば、その重複をある程度整理する、ざっくりとした共通化が必要なのではないかと思います[3]。
今日は時間がありませんが、この議論がこれから先深まっていけばいいかなと思っています。
テスト駆動開発の知識がもっと広まっていくことで、この先の議論ができると思っています。
はい、では最後に家永さん。
家永さんの発言
では、あえて重複はなし(笑)。
普通のプロダクトコードは重複をなるべく減らして、なるべく意図的なことになっているはずなのに、テストの重複を削ったら読みにくくなるというのは、直感的に何かおかしなことをしてるんじゃないのかなと。
実はテスト側のリファクタリングに関する意識というか、まとめ方っていうのが、皆共通のものも何も持っていなくて、それをバラバラに皆まとめちゃってるところがあるのかっていうのが、一つあります[4]。
もう一つ、私の仕事はどちらかというと、新機能開発Toいうより若干メンテナンスモードに入っているところなんですけれども、その視点からいくと、なにか1つ修正したタイミングで、バーって赤色になるのを見ると、すごい悲しくなる(笑)。
実はそれって、重複したテストが原因で、妙なことになってるんじゃないかなっていう後悔感というか、そういう経験を持っているんで、普通に重複ありって言われると、ちょっと困るなっていうのが(笑)。
なるほど。
単に重複あり/なしだけでなく、新規機能を開発する際は重複ありだけど、メンテナンスを続けていくときは意味のない重複は悪だという視点をとる、というハイブリットな考え方もありえそうですね。
実際にテスト結果が真っ赤っかになってしまうと、萎えてしまうこともあります。テストのリファクタリングというキーワードですね。テストのリファクタリングというトピックは、非常に大きいトピックですので、申し訳ありませんが、またの機会という形になってしまうと思います。
なぜ大きいトピックかという説明を、少しだけしましょう。リファクタリングをするためには、テストが必要ですというのが、リファクタリングの大原則としてあります。ということは「テストのリファクタリングを行うときには、テストのテストがないといけない」という話にどうしてもなってしまいます。要するに、テストのテストとは何ですかという話をこれからしていかなければならないのですが、本日はちょっと時間の都合でもう話すことはできません。テストのテストに関しても、『達人プログラマー』(アスキー刊のほう)で少しだけ言及がありますので、興味のある方はぜひ読んでみてください。
連載の終わりに
時間も、もう終わりに近づいてきてしまいました。
まずこちらに来ているみなさん、本日お集まりいただき本当にありがとうございました。
そして、この連載をご覧いただいたみなさん、本当にありがとうございました。