モジュール単体が正しく動作するかを確認するテスト。
単体テストとは、モジュール単体が正しく動作するかを確認するテストのことです。モジュール(=プログラムを構成する部品。関数やメソッドなど)を1つずつ取り出して、入力に対して期待どおりの出力が得られるかを確かめます。
大きなプログラムはいきなり全体を確認するのではなく、まず小さな部品ごとに正しさを保証してから組み立てていきます。単体テストは、その「部品ごとの確認」にあたる、テストの中で最初に行う工程です。
身近な例で考えると、車を組み立てる前に、エンジンやタイヤを1つずつ検査することに似ています。部品の段階で不良を見つけておけば、組み上げた後で原因を探すより、ずっと簡単に直せます。上の図解のように、モジュールごとに入力と期待する出力を用意して確認します。
単体テストの対象は、個々のモジュール(プログラムの最小単位)です。具体的には次のようなものを1つずつ確認します。
・関数・メソッド:ある入力に対して正しい計算結果を返すか
・分岐の各経路:if の「真のとき」「偽のとき」それぞれが正しく動くか
・境界の値:0や上限値など、境目になる値で正しく動くか
・異常な入力:想定外の値を渡したときに適切に処理できるか
単体テストでは、モジュールの内部の処理に注目して「すべての分岐を通るか」を調べることが多く、これをホワイトボックステスト(中身の構造を見て行うテスト)と呼びます。たとえば if 文があれば、条件が成り立つ場合と成り立たない場合の両方を試します。
上の図解の「計算」モジュールのように、入力と期待する出力の組み合わせをいくつも用意して、すべて期待どおりになれば合格です。1つのモジュールに対して多くのパターンを試すことで、その部品の正しさを確実にします。
単体テストと混同しやすいのが結合テストです。両者は確認する範囲が異なります。
・単体テスト:モジュールを1つだけ取り出し、それ単独で正しく動くかを確認する
・結合テスト:単体テストを通った複数のモジュールを組み合わせ、それらの連携(受け渡し)が正しいかを確認する
順番は必ず「単体テスト → 結合テスト」です。先に部品ごとの正しさを保証しておくことで、結合テストで問題が出たときに「連携の部分が原因だ」と切り分けやすくなります。
上の図解のように、単体テストは1つの部品の中身に注目し、結合テストは部品と部品のつなぎ目に注目します。テストは小さい範囲から大きい範囲へと段階的に進めていくのが基本です。
モジュールを単体で動かすには「呼び出し元」や「呼び出し先」が必要になることがあります。でも単体テストの段階では、まわりのモジュールがまだ完成していない場合も多いです。そのとき使うのがドライバとスタブという仮の部品です。
なぜ必要か。モジュールを単独でテストしたくても、「呼び出してくれる上位のモジュール」や「呼び出す先の下位のモジュール」が未完成だと動かせません。本物の代わりに簡単な仮の部品を用意することで、テスト対象だけを単独で動かせます。
・ドライバ(=仮の呼び出し元):テスト対象を呼び出してくれる上位モジュールの代わりに使う仮の部品。「〇〇を引数にして呼び出す」という操作だけを行う
・スタブ(=仮の呼ばれ先):テスト対象が呼び出す下位モジュールの代わりに使う仮の部品。呼ばれると決まった値を返すだけで、複雑な処理はしない
たとえば「計算」モジュールをテストするとき、それを呼び出す「画面」モジュールがまだなければドライバが代わりに呼んでくれます。計算に必要なデータを持つ「データ取得」モジュールがまだなければスタブが決まったデータを返してくれます。こうして周囲が揃っていなくても、1つのモジュールだけを先にテストできます。
ソフトウェアのテストは、小さい範囲から大きい範囲へと段階的に進めます。単体テストはその最初の工程です。
・単体テスト:モジュール1つを単独で確認する(←今ここ)
・結合テスト:単体テスト済みのモジュールを複数組み合わせ、連携を確認する
・システムテスト:システム全体を動かして、仕様どおりに動くかを確認する
・受入テスト:実際に使う人(発注者など)が、要件を満たしているかを確認する
なぜこの順番なのか。小さい部品が正しいという土台があってこそ、「組み合わせの問題なのか部品自体の問題なのか」が分かります。単体テストを省いていきなり大きな範囲を動かすと、バグが出たときにどこが悪いかを探すのがとても大変になります。段階的に進めることで、問題の原因を早く・確実に見つけられます。