システムのタイマーをラップしてテスト工数を削減する

システムのカレンダーやタイマーをロジック内から生のまま取得していると、テストの度にシステムのカレンダやタイマーを変更しないといけないため、やたらとテストが面倒になる。

たとえば、現在時刻を取得して稼働時間かどうかを判定する処理があったとする。システムのタイマーから現在時刻を取得して判定する事になるわけだが、この単体テストはどうなるだろう?

開発用クライアントPCでテストするのなら、割と簡単かもしれない。PCの時刻を変えて、テストして、テストが終わったら元に戻せばいい。しかし、サーバなどで簡単にシステムのタイマーをいじれない場合、どうやってテストすればいいだろう?

あるDBなんかは、システムのタイマーが巻き戻ると不具合を起こしたりする。DBに限らずタイマーの巻き戻りを考慮してないソフトなんかいくらでもある。こんな環境ではおいそれとシステムの時刻を変えるわけにはいかない。
仮にシステムの稼働時間の範囲が朝5時から夜11時までだったら、その時間まで待ってテストするわけ?
とってもめんどうだよね?


こういった場合、システムから直接日付やタイマーを取得するのではなく、間にテスト用に使う日付や時刻を返せるような仕組みを持ったラッパーメソッドを用意するとテストが簡単になる。

たとえば、起動時に特定のプロパティを指定すれば、その値を日付や時刻として返すようにラッパーメソッドを作っておくのだ。
そうすれば、いちいちマシンの日付を変えずにテストできる。
システムの時刻が変更できない環境でも深夜まで待たなくてすむ。

カレンダやタイマーに限らず、なんらかのロジックで分岐の条件として使う情報は、ロジック内で取得するのではなく、ロジックの外から渡してやった方がテストが楽になる。

DB接続だってロジックの外からテストDBにつながったDB接続を渡してやれば比較的楽にテストできるようになる。

このエントリではユニットテストの例を示したが、システムテストや受け入れテストでの扱いは
システム/受け入れテストで日付型と時間型をテストするが詳しい。


また、こういった、いかにテストしやすく作られているかをソフトウェアのテスト容易性といい、ソフトウェア品質特性ISO9126では保守性のうちの1つとして定義されている。ISO9126についてはオージス総研で公開されいているこの記事がわかりやすいと思う。

この例では比較的簡単なユニットテストレベルでの例を示したが、
先に示した記事の「2.1 機能要求と機能外要求」で、

実際のソフトウェア開発の現場では、機能要求と比較して機能外要求は識別しにくいということをよく耳にします。 その反面、ほとんどの機能外要求はソフトウェアアーキテクチャに影響します。 ソフトウェアアーキテクチャは、アプリケーションの設計全体に影響し、ソフトウェアアーキテクチャ設計にはエンジニアの高い技術力が求められます。 このことから、機能外要求の定義に漏れや誤りがあると、ソフトウェアアーキテクチャへの追加や変更に大きなコストや時間がかかることになります。 そのような事態を避けるためにも、機能外要求を網羅的に確認し、プロジェクトが見逃してしまった暗黙の要求としてしまわないことが重要です。

と述べられているように、システムのアーキテクチャレベルでいかにテストしやすく設計するかという事が大事です。
いざテスト工程になってメンテナンス用のハッチを取り付けようとしても遅いのです。