仕事の休憩にふと、そういえば知り合いの社長さんが「学生さんがテストの有用性に気付いてくれない」とぼやいていたのを思い出していました。
そこで、休憩がてらテストをすることによる利点について、いくつか考えてみようと思います。
ここでいうテストとは
その前にここでいうテストについてはっきりしておきましょう。
ここでいうテストとは
- 作成したプログラムコードの動作を検証・確認するコード片のこと
- 基本的に常に成功するはず
- テストフレームワークを使うことで、自動的・半自動的に定期実行できるテストケースのこと
わたしについて
なお、わたしは本業でチームプログラミングをやったことはなく、フリーランスとして受注で小規模なプログラムを作ったり、講習用の簡易プログラムを作る程度です。
チーム開発はやったことがないですし、お客様や上司に提出するためのテストコードを書いたり、カバレッジ計測などを行うこともありません。
会社で製作するようなガチガチのプログラミング環境とはかなり違ってくることがあると思いますので、あしからず
テストをこまめに作り込むことのメリット
テストをこまめに作り込むことによって感じるのは、だいたいこんな感じか。
- プログラムのデグレードにいち早く気付くことができる
- プログラムのメソッドひとつひとつを多方面から検証することにより、(実運用上で遭遇しづらい)準正常系・異常系の動作を明確にすることができる
- テストケースを考えることによって、プログラムコードに「何が足りないのか」を洗い出すことができる
- 早い段階からとりあえず「動くもの」が見られるので、モチベーションの維持にもつながる
- 自分のコードに自信が持てる
- プログラムをメソッド単位で実行することで、自分が書いたコードがきちんと動作するという証明をすることができる
- 修正が怖くなくなる、気軽に機能修正ができる
- 結果的にモジュールの構成をシンプルに保てるようになる(シンプルにしないとテストができなくなるため)
- こまめに動作検証をすることができるので、エラーを発見したときに必要なステップが少なく済む
- いざ実運用上でバグが起こった際、問題箇所の特定にかかる時間を短縮しやすい(モジュールの各種挙動が明確にできるため)
準正常系・異常系の動作を明確にすることができる
単体テストでは、メソッドに気軽にさまざまなパラメータを送り込むことができるので、実運用上ではなかなかお目にかかれないものの、仕様上入力があり得るような様々なパラメータを受け取ったときに、メソッドがどういう挙動を示すのかを明確にすることができます。
また、テストである程度挙動を明確にしておくと、想定していなかったことにもある程度動作が予想できるようになるため、お客さんに「これこれこういうことをしたときはどうなるの?」的な質問をされたときに回答しやすくなります。
プログラムコードに「何が足りないのか」を洗い出すことができる
さまざまなテストケースを考えることで、「あ、このパラメータが来たとき(来なかったとき)の処理が抜けてたな」ということに、より早く気付くことができます。
実運用上では考えられないことでも、異常値に対する処理をしっかり書いてモジュールの完成度をとりあえず上げておくということは、後々プログラムに機能追加をしたときのトラブルを減らすことにもなります。
早い段階からとりあえず「動くもの」が見られる
テストを作っておくのは、山登りの際に足場を固定するようなものです。
固定されていない足場を使うと、安心して体重を預けることはできませんし、重心がブレてしまうので危険です。
足場をがっちり固定しておくことで、プログラムコードを安心して使うことができるようになります。
エラーを発見したときに必要なステップが少なく済む
とくにGUIのあるアプリなどだと、動作検証して、結果を得るまでに行わなければいけない操作が多いため、動作の検証に時間がかかりがち。
GUI上で問題が発生して、検証していった結果些細なミスだった となると、開発してる側もテンションが下がります。
どんなテストを作ると良いか
この辺についてはかなり慣れの問題にもなりそうな気がしますが。
いわゆる境界値(許容する値の範囲ギリギリの値と範囲外ギリギリの値)や、コード的にやや不安な値(複雑な計算式を使ったり、可読性の低いコードブロックを通ったりする場合)、値が設定されなかったとき(Nullが設定されていたとき、そもそも値が設定されなかったとき)などはひととおりカバーしておくと良いかと思います。
また、実運用がはっきりしている場合は、実際に与えられる値(実際に引き渡される画像やPDFなどのデータ)などもいくつか検証しておくと、安心できます。お客様から検証データがもらえる場合はもらっておくと良いでしょう。
また、実運用上はあり得るはずだけど滅多になかったり、入手が難しいデータ(A0サイズのPDFや、ページサイズが1ページごとに異なるPDFファイルなど)についても、できればそれっぽいのを生成してテストするなりしておきたいところです。
テスト用のファイルを作るためのスクリプトなども必要なら作っておくと良いかと。
とくにお客様対応のプログラムでもそこは結構自由に作り込めるので、なんとなく周辺技術を学ぶにもちょうど良かったりしますし。
テストを作るタイミングはいつがいいか
個人的には、わたしは次のような順番でコードを書いています
- テスト対象のモジュールを作る
- モジュールのテストを書く
- テストをパスするまでテストとモジュールの修正を繰り返す
テスト製作はなるべく最初から着手した方が良い と思っています。
というのも、途中から・終盤からテストを書き始めると、とにかくテスト製作ばかりが続く日が発生してしまい、モチベーションも下がるし、作業工数も読みづらいし、大変でした。
また、ある程度作り込んでからテストをしようと思うと、いざテストがしやすい風にコードを書き直す手間が発生することもありますので、非常によくありません。
いわゆるTDDのように先にテストを作ってから というのも良いのだろうと思いますが、正直作る前はメソッドの仕様もはっきりしていないことがあったりして、自分にはどうも向いていませんでした。
バグを見つけたときにもテストケースを作成する
また、実運用や、さらに下流の行程(運用に近いフェーズ)でバグを見つけたときは、それに関するテストコードも作っておくと良いでしょう。
特に再現性が高いバグの場合は、そのバグが確実に再現するテストを作って、バグが発生しなくなるまでそのテストを使ってコードを修正していく というやり方をしていくと、バグの完治を明確に感じることが出来、安心感が増すと同時に、モチベーションも上がると思っています。
まとめ
個人的には、テストはなるべく最初のうちから、こまめに作っておくのが良いと思います。あとでまとめて作っていくのはモチベーションの維持も大変ですし、テスト対象のコードを修正しなければいけないケースが発生することもあるのでよくありません。
テストを作っていると、モジュールの強度が上がっていくのを体感できますので、気分も良いです。
強度が高いモジュールは多少の仕様変更にも耐えられますし、変更が必要になった場合も、どう変更すれば良いかが分かりやすくなります。
テストの良さを理解するにはやはり実践が一番にはなりますが、とりあえずこの辺が言葉だけわかってるだけでも、ある程度良さが分かってくるのではないでしょうか。