
単体テストを信用するな
システム開発において避けて通れない工程のひとつが「テスト」。人間の手でプログラムを作る以上、バグ(不具合)は必ず混入してしまいます。ボタンを押しただけでエラーが出るような分かりやすいバグはともかく、特定の条件下でのみ発生するようなバグは一見すると正しく動いているように見えてしまうため、リリースまで気づかれないこともあります。そうした事態を防ぐためにテストを行い、可能な限り早い段階でバグを洗い出して修正するのです。
その最初の工程が「単体テスト」です。多くの場合、単体テストはプログラマ自身が自分で作った機能を一つひとつ検証する作業を指します。自分で書いたプログラムの挙動はよく理解しており、想定と異なる動きをすれば即座にバグだと気づけるので、一見するともっとも効率的なテストのように思えます。
しかしここには大きな落とし穴があります。それは、プログラマが「正しい」と信じている挙動が、必ずしも設計者の意図と一致しているとは限らないことです。設計者は、実際にシステムを利用するユーザーと打ち合わせを重ねて設計書を作成します。設計書はユーザーにも分かる言葉で書かれているため、そのままプログラムに落とし込めるとは限りません。設計書を参考にしてプログラムを作成していく段階で誤解が生じたり、あるいは無意識のうちに都合の良い解釈をしてしまうこともあるでしょう。そうなると、プログラマ自身が「意図したとおり正しく動いている」と感じたとしても、実際は設計書やユーザーの意図とは異なる動作をしている可能性があるのです。つまり、設計者の意図と食い違っていても単体テストは通ってしまうので、これだけでバグを取り除くことはできません。
この食い違いを発見できるのは、次の工程である結合テストです。結合テストでは(多くの場合)設計者自身がテストを行うため、設計意図に沿っていなければ不具合として検知することができます。だからこそ、私は「単体テストを信用するな」と言いたいのです。単体テストをいくら丁寧に実施しても、設計者の意図から外れた部分までは検証できません。結合テストで改めて確認し直す必要があります。
では単体テストは無意味なのかといえば、そうではありません。もし単体テストを全く行わなければ、結合テストに入った途端にシステムエラーが頻発し、テストが進まなくなるでしょう。単体テストは結合テストをスムーズに進めるための「地ならし」だと言えます。プログラム的な単純バグを早い段階で取り除き、次の工程に余計な負担をかけないことが重要なのです。
にもかかわらず、時折「単体テストで細かい確認は済んでいるのだから、結合テストでは大まかな動きだけ見れば良い」と言う人がいます。しかし、それは極めて危険な考え方です。前述の通り、プログラマが「この動きが正しい」と思い込んでいれば単体テストは問題なく通ります。そして結合テストで「細かい確認は不要」と判断されれば、設計意図とのズレが放置され、リリースまで誰も気づかないかもしれません。
単体テストには確かに意味があります。しかしそれを過信してはいけません。単体テストはあくまで結合テストに進むための準備であり、本当の意味で設計意図に合致しているかを確かめられるのは結合テスト以降です。過信せず、役割を正しく理解して取り組む姿勢こそ、システム開発を成功させるうえで重要なのだと思います。
※このコラムは、筆者が個人事業主時代に執筆した文章を推敲しなおして再掲したものです