C0カバレッジ100%のためのDSL

Railsでちゃんとした製品を作るとしたら自動テストは欠かせません。型チェックのある他の言語でもテストケースは書くべきですので、言語としての型チェックのないRubyでそれをしないでいいはずありません。

ただし単にテストをするべきと言っても、バグを減らすためにはコードのカバレッジが重要です。RubyにはRCovというカバレッジ計測ツールがあります。「メンテナンスは考えないでいいからとにかく実装を!」(と言っても結局はメンテすることが多いはずだけど)というプロジェクト以外は、必須のツールです。

で、このRCovですが、C0、C1、C2、C3kとあるモジュールのテストカバレッジ(テスト網羅性 http://itpro.nikkeibp.co.jp/article/COLUMN/20071026/285596/?P=3)のうち C0をサポートしているだけですのでご注意を。

僕がテストを書くタイミングは以下の4つにするように心がけています

  1. アプリケーション、プラグイン、gemなどのコードを書く前
  2. バグが見つかったとき
  3. 不安になったとき
  4. rcovで100%に達していないとき

アプリケーション、プラグイン、gemなどのコードを書く前

これは経験的なもので、後からテストを書くのがしんどいからです。プロジェクトによってはテストを書くフェーズを実装の後にした方が管理しやすいからということで、実装と単体テストを分ける場合もありますが、ここは譲れないです。最悪 単体テスト--> 実装、という流れにするくらいの気持ちで交渉します。そんなことにはなったことないですけど。

バグが見つかったとき

最近参加したプロジェクトではtracでバグなど管理していますが、チケットのないコミットを原則禁止しています。バグがチケットで管理されていれば、大抵それに対する修正も発生するはずですので、それをコミットしますが、その際にちゃんと直したことが分かるようなテストを記述します。これを書いておくと、もしかして修正ミス?っていう心配が減ります。

心配になったとき

基本チケットのないコミットは禁止したいので、テストといえどもむやみにコミットしたくないです。なぜそのテストが必要になったのかが分からなくなるので。しかし、無性に心配になってしまうことはあります。そういうときはその心配をチームで共有するためにもチケットに上げておくのがいいと思います。で、そのチケットにテストをコミットしておくと。

rcovで100%に達していないとき

100%に達することはバグを減らすための手段でしかありませんが、100%かどうかというのはバグを発見する上でも非常に重要です。なので、100%に達していないコードを見かけたらテストを追加するようにしています。

で、DSLですよ

ここからが本題なのですが100%を達成させるための一番の近道はできるだけテスト対象となるコードを書かないことです。
テスト対象が少なければ必然的にテストコードも少なくなります。

例えばバリデーション。validateメソッドをオーバーライドしてバリデーションを記述することも必要な場合もありますが、クラスメソッドのvalidates_xxxxを使えば、クラス定義時にそのメソッド呼び出しは実行されるので、カバレッジ100%を達成するためのテスト対象を減らすことができます。

あとよくあるのが、複雑なSELECT文の組み立て。これもDSLちっくにSELECT文を組み立てるクラスをアーキテクト(じゃなかったらチームに一人はいるであろう詳しい人)が作ってあげれば、アプリ開発者がそれをテスト対象外にすることができるはずです。もちろん、アーキテクトは自分の欠いた部分のテストを書きますし、またアプリ開発者もそのクラスを使う部分はきっとコードを書くはずなので、使う部分としてのテストは必要になると思いますが。

100%だからって

繰り返しますがRCovで100%を達成することはバグを減らすための手段であって、100%を達成してもバグがでることはあります。っていうかDSLを多用してテスト対象となるコードを少なくしても、バグが減らないんじゃ意味ないっす。もっとうまくやる方法もあるような気がするんですけど、それは今後の課題にします。