Line 1: Error: Invalid Blog('by Esehara' )

または私は如何にして心配するのを止めてバグを愛するようになったか

>> Zanmemo

あと何かあれは 「esehara あっと じーめーる」 か @esehara まで

ユニットテストを書かないことについて

はじめに

 最近は、同じ職場で働いている人に対して、『テスト駆動開発入門』の本を貸したり、自分自身でも全く更地のところにユニットテストを書くという作業をやったり、あるいは実装中にもユニットテストを書かないと、コードを書く手が少し滞ってしまうくらいには、テストに依存している自分がいる。

 さて、ここ最近で一連のテストの話が各方面から出ていて、それらの議論について興味深く感じる一方で、たとえば自分はそうだけど、「執拗にテストを書いているけれども、これで前に進んでいるんだろうが」という罪悪感みたいなのを抱えている人というのは、それなりにいるんじゃないかと。特にユニットテストを腐らせて、テスト自体を負債にしてしまった人であるなら特に。

 ここ最近の、アジャイル開発であったりとか、あるいはプログラマのための本みたいなのを開いたりすると、たいてい「他のことは良いからテスト書け」と載っている一方で、見回してみると、愚直にテストを書いている人間は俺一人しかいなかった、みたいなことがちょくちょくある。

 もちろん、内心は自分で苛々したりするような、性悪な自分がいる一方で、しかしそのことで苛々していることに苛々している自分もいる(これは単なる愚痴にしかならないので)。「普通やるだろ」と思っていることと、「いや、その普通って何なの」という話になる。

 そこで、一連の議論を参考にしながら、なぜユニットテストを書かないのだろうか、そしてなぜそれでもユニットテストを書くのか、ということを考えた方がいいのかなという気がしている。以下に書かれていることは、「アジャイルとはドキュメントを書かないこと」くらいの誤解が多く紛れ込んでいると思うけど、自分が整理するために、ちょっと書いておこうと思う。

 あ、それと以下のことは、自分がウェブプログラマーとして、サービスを作ったりした中で感じたことなので、他の開発だとちょっと諸事情が違うかもしれない。

ソフトウェアの二つの側面

 恐らく、ソフトウェアには二つの側面に分けられると思う。

 一つは「お金を稼ぐ」という側面と、「本来掛かる筈だったお金を節約する」という側面だ。片方は、いわば非開発者側のサイド(ユーザー)に関わることで、もう片方は開発者側のサイドに関わる。

 「お金を稼ぐ」という側面を考えた場合、基本的には機能を作成することに関わると思うし、あるいはアプリを立ち上げるといった側面もあると思う。受託開発なら、言われた機能を実装することで、「ではお支払いします」という話になるだろうし、スタートアップなら投資をもらったりするだろう。そのサービスが幸運なら、既にお金を払うユーザーもいるだろう。

 この「お金を稼ぐ」という側面に着目した場合、ユニットテストに対してお金を払うわけではない。ユニットテスト自体は、ユーザー側に対して何かを提供している、というわけではない、という側面は確かに指摘出来る。

 たとえば、『アート・オブ・アジャイルデペロップメント』について、「顧客の仕事がプロダクトの価値を最大化することなら、プログラマの仕事はコストを最小化することだ。プログラマには、計画にあるストーリーを実現するのに最も効果的な方法を見つける責任がある(27頁)」という一節がある。これは役割の話でもあるのだが、しかし、プログラマが「これからかかるコストを減らしていく」という役割があるんだろうな、ということは頭の隅にあっても損ではない気がする。

アート・オブ・アジャイル デベロップメント ―組織を成功に導くエクストリームプログラミング (THEORY/IN/PRACTICE)

アート・オブ・アジャイル デベロップメント ―組織を成功に導くエクストリームプログラミング (THEORY/IN/PRACTICE)

  • 作者: James Shore,Shane Warden,木下史彦(監訳),平鍋健児(監訳),笹井崇司
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2009/02/18
  • メディア: 大型本
  • 購入: 18人 クリック: 336回
  • この商品を含むブログ (96件) を見る

テストと負債

 例えば、PublicKeyに載っているテスト駆動開発の効果に関する記事を見ると、「TDDを実施した場合に、コーディング(実装)の時間が16%増えた」ということが述べられている。これに関しては、テストの熟練度によってかなり幅が出ると思われるが、実装に時間がかかる、あるいはコーディングの時間が長くなるという自体は、その機能実装が実現するまでの時間が掛かることを意味する。これは懸念点だ。

 もちろん、よく見てみればわかるが、実際はデバッグの工数を削減すると感じる効果が殆どあるので、「実装の時間がかかる=実際の工数が跳ね上がる」というわけではない。

 ただ、ユニットテストも負債になるということはおさえないといけない。ユニットテストが負債になってしまった場合こそ、そのユニットテストに対して忌避感が生まれると思う。

 例えば、その機能の仕様が固まっていない場合がある。つまり、ある程度プロトタイピングして、挙動を確認するといった場合、そもそもユニットテスト自体が足かせになる場合がある。例えば、自分の失敗だと、変更が確実に行われるViewのレンダー部分に関して、ユニットテストを入れ込んだ結果、デザイナーから受けとったHTMLを反映させるさいに、確実にユニットテストが壊れて収集がつかなくなったことがある。

 また、ユニットテスト自体を、共通化し、リファクタリングする時間をいれないと、それこそユニットテストの破壊自体に対して、余計な時間を取ってしまう。テスト自体も、また負債になりうる。とすると、ユニットテスト自体にも、その周辺の技術が必要になる。

 また、ユニットテストについて、そもそもそのテスト自体を誰が正しいものとするのか、というのもある。例えば、自分もたまにやって怒られるのだが、仕様の勘違いのまま、ユニットテストを書いていたことがあり、間違った仕様に対してバグが生まれるということがあった。この点に関しては、コードレビューなり、ペアプロなりが重要だと思う。あと、継続的インテグレーションで、何かの機会に自動テストをするみたいなのも。

ユニットテストは必ずしも設計を正しいものとしない

 これはあとでブログの記事にしようと思うけど、「設計過多」な部分と、「設計過少」というのに悩まされてきた。たいていはどっちかにぶれるものだし、そういうものだと割り切れるが、しかし設計を考える上において、ユニットテストというのはどこまで強いのかというとなかなか難しい。

 教科書的に言うと、ユニットテスト自体にも、設計をよくする側面がある。それは、「テスタブル」である、ということだ。つまり、その挙動に対してテストをしやすくなる側面がある。これは馬鹿にならない。

 しかし、大局的な設計を考えた場合──つまり、そもそもデータベースどうするのとか、あるいはどういう風な形のモデルとして実装するのか(ドメイン駆動開発的なモノを想像してもたぶんいい)というのは、ユニットテスト自体ではどうすることもできない。

 もちろん、設計自体が、最初から正しいということはありえない。だいたいはベストをつくしても、実装段階で意図をしないことがある。だから、『ドメイン駆動設計』という本自体に関しては、リファクタリングをやり続けることによって、モデルを洗練させていくという側面があることは強調されている。その前提としてユニットテストがあるというのはあるだろう。

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

「だってそれを僕は保守しないから」

 先ほど、上でアプリを立ち上げること自体、あるいは機能開発がお金を稼ぐことだ、という話をしたのだけれど、例えばそのサービスを一年間はずーっと面倒を見ることを考えた場合、リファクタリングしたり、ユニットテストしたりしながら、今後たまりゆく負債に対してなんとか出来るように防波堤をたてよう、という話になると思う。

 しかし、じゃあそれが「納品してお終い」ということになると、ユニットテストに対するモチベーションも低くなってしまうのかな、とも思う。前にも言った通り、ユーザーは「その機能にしか着目しない」側面があり、その機能が実装されていたらOKになる。そうすると、「その機能の部分だけをブラックダストボックスに押し込める」という実装になってもいい。

 とはいえ、そのサービスだって、よほどキャンペーンとかで一時的にしか使わないものではない限り、出来るなら長く運用したいし、運用の間で機能改善したいよね、と思うこともあると思う。そういった場合、そのように省いたコストは誰かに押し付けることになる。

 もちろん、最初からそういう風に悪意があってアプリを作っているわけじゃないとは思うんだけど、しかしやはりどうしても「誰かに押し付ける」という側面は確実に出てきてしまう。すべてのコストを担えるわけではないし、その都度ベストを尽くして負債になるんだけど、しかし何処かで「保守しないから」ということを言い訳にしてしまうことがあったのは懺悔する。

「ユニットテストって何すればいいの」

 そういった、ユニットテストをやっていきましょうよ、という文化について、そもそもテストって何をすればいいの、という話になったりすることがある。もちろん、そのときに『テスト駆動開発入門』の本を渡したり、自分が過去に書いたコード(GitHubに載っているコード)を見せたりするんだけど、そういうのを見てもピンとかない人というのは確実にいる。

 とはいえ、その人が悪いとは必ずしも言えない。コードは書いて、機能を実現する力はある。コードがどんなにあとあと辛くても。で、そういう人が頑張って開発したりしていると、そういうテストについて、そもそもわかってもらえないという場合はある。

 もちろん、重要なのは、ユニットテスト自体ではなく、ユニットテストというのは、コードに奉仕する存在だから、そういうほうがその人にやりやすいのならば、それでいいと思うし、そういう人がいないと「これかかりすぎじゃない?」というようなチェックが出来るとは思う。だからといってユニットテストを書かなくてもいいよねーみたいな雰囲気になるのもちょっと違うと思うけど。

テスト駆動開発入門

テスト駆動開発入門

  • 作者: ケントベック,Kent Beck,長瀬嘉秀,テクノロジックアート
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2003/09
  • メディア: 単行本
  • 購入: 45人 クリック: 1,058回
  • この商品を含むブログ (161件) を見る

まとめ

 で、最後に、自分の印象は下のような感じ。

  • ソフトウェアには「お金を稼ぐ」ということと「本来掛かった筈のお金を抑える」という側面がある気がする
  • ユニットテストは「本来掛かった筈のお金を抑える」ためのものの側面はある
  • ユニットテストは負債化するので、リファクタリングしたりしないと足かせになったりしそう
  • ユニットテストはそれを有用になるような期間・技術もそれなりにあると思う

 結果として、ユニットテストはそれはそれなりに技術的なものだし、僕は僕のために書いて欲しいなと思う一方で、「書く側」が「なぜ書かないのだろう」ということを考えると、自分のやっている「テストをやるってなんだろう」ということがわかる気がすると思う。

蛇足

 自分としては、状況によるけど、基本ユニットテスト書いた(書ける環境)の方が幸せになれるとは思ってます。