テストをどこまで書くか

CROSS2014で以下の2つのセッションにお招きいただきお話をさせていただいた。ありがとうございました。

セッション中はもちろん、その後の懇親会でもいろいろな方におはなしを伺えてかなり勉強になった。テストやコードレビューなどの開発フローについてのお話が多かったので、そのへんの話で考えたことを少し書いていこうと思う。

とりあえずテストの話から。元気があったらコードレビューのはなしとかも別のエントリで書きたい。 => コードレビューの話は id:shiba_yu36 さんの記事がわかりやすい コードレビューを円滑に行いたい (#cross2014 のお話) - $shibayu36->blog;

テストをどこまで書くか

naoyaさんのセッションでテストをどこまで書くかについての議論があった。結論として「コストと効果を見極めていい具合に書こう!」という感じになったのだけども、いい具合というところが一番むずかしい。

たぶん、漠然とテストをどこまで書くか書かないかという話はできなくて、ソフトウェアごとに保証したい品質やその程度に合わせて、テストをどこまでやるかをいうことを丁寧に考えないといけない。その考えた結果がいい具合ということになるのだと思う。

前提

naoyaさんのセッションでも言われていたけれど、テストの話をするときには、まず前提を話さないとコミュニケーションが失敗がち。自分が所属しているはてなでは、いくつかサービスを数年にわたって運用している。そういったサービスを実現しているソフトウェアには以下の様な特徴があることが多い。

  • ソフトウェアの寿命が数年単位と長い
  • ソフトウェアの根本的な設計や機能が何度も変化する
  • ソフトウェアの開発メンバーが変わることがある

数年にわたって動作するソフトウェアが、価値を生み出し続けるためには、継続的に変更が必要だし、時にはそれが大きな変更になることもある。開発メンバーが変わることもあるので、変更者が必ずしも変更するソフトウェアのことを熟知しているわけではない。

テストを書く理由

上にかいた前提のもとでは、多くの場合、以下の様な理由でテストを書いていると感じる。

  • 1.ソフトウェアの変更可能性を維持するため
  • 2.ソフトウェアの機能性/信頼性を保証するため
  • 3.開発効率を高めるため

ソフトウェアの変更可能性を高めるのにテストは有用だ。回帰的なユニットテストを書いておくと、別の変更によって何かがこわれてもすぐに気づくことができる。テスト可能なコードを書くことで良い設計になったり、テストがコードの意図を残したドキュメントになることでソフトウェアの理解性が高まる効果もある。

ソフトウェアの機能性や信頼性の保証にもテストが利用できる。ソフトウェアがちゃんと機能を満たし、異常事態に対応できるかを確かめるのにテストが必要である。

開発効率を高めるためのにもテストは便利だと感じる。ソフトウェアに何か機能を追加すると、テストがあろうがなかろうが、様々な入力で動作することをたしかめないといけない。実装が進めるたびにブラウザを起動して、フォームになにか入力して、結果を確認するみたいなちまちましたことを繰り返し行うのは効率が悪い。

数年の間動くサービスを作っているという前提では、1のソフトウェアの変更可能性を維持するのがすごく大事で、コストをかけてもテストを書く一番の理由になっていると思う。2や3については必要に応じてコストをかける。

テストをどこまで書くか

なんのためにテストを書いているかを考えながらテストを書くと、ある程度どこまで書けばよいか基準を考えることができると思う。はてなでの例に照らし合わせて考えてみる。

変更可能性の維持を目的にテストを書いているのならば、代表的な正常系と異常系でテストが通過していることを確認したりして、対象のコードのすべての命令が一度は実行されている程度のテスト( C0 程度 )があれば良いと思ってる。呼び出しているメソッドに大きな変更(メソッドのシグニチャが変わるとか)があったときにテストが落ちるようになっていれば、他の場所の変更でコードがこわれたことが検知できる。

機能性や信頼性が重要な部分(課金系の機能とか)でそれらの品質を保証したいテストを書きたいのであれば、一歩踏み込んで、あり得るすべて入力や実行経路での動作を確認するテストが必要になると思う。厳密な保証が不要な部分であれば、滅多にない入力の組み合わせなどについてはテストをしないこともできる。

開発効率をあげるためのテストのみを書いているのであれば、開発中のソフトウェアの動作の確認ができさえすれば内容はなんでも良いかもしれない。

naoyaさんのセッションで、テストをどの程度までやるかの基準としては、テストはC0を満たす必要があるのではないかと発言をしたのは、ソフトウェアの変更可能性を維持するためには、最低限それくらいのテストが必要だという文脈だった。もちろん他の目的でテストをかいているとC0ではやりすぎかもしれないし、C0では足りなすぎるということがあると思う。

つまりどうしたら

ソフトウェアの品質を高めるためにテストを書く、というだけではおおざっぱすぎて、結局何を書けばいいかわからなくなってしまう。そうではなく、まず、目的をもってテストを書くことが大事だと思う。開発しているソフトウェアに合わせてどういった品質をどの程度まで保証したいかということを、ちょっとでも意識できると、テストをどこまで書けばよいかという基準が見えてきて、テストを異常に書きすぎたり、書かなすぎたりして意味のないテストになるということは減るのではないかと思う。