今回は、テスト工程の1つである単体テストにフォーカスを当てます。前回、前々回ではテストケースを作成する技法を見てきましたが、そこで作ったテストケースをどのように実行するかという観点で、単体テストの基本的な進め方と、ツールを用いた単体テストの実行方法について解説していきます。
単体テストとは
単体テストとは、ソフトウェアを構成する最小単位である関数やメソッドに対して品質を確認する作業です。ソースコードレベルでのテストと考えるとわかりやすいでしょう。
一般的なテストにおいては、先入観なくテストするためには、テスト対象を作った人以外がテストをすることが望ましいのですが、単体テストに関しては、作業効率を考慮して、ソースコードを作ったプログラマ自身が実施するのが一般的です。
また、単体テストはツールを用いることで効率よく実施できます。よく使われるツールには、xUnitと呼ばれる単体テスト用のテスティングフレームワークがあります。これは、さまざまなプログラミング言語に対して提供されており、これにより容易にテストの実行や結果の確認ができます。
単体テストの進め方
通常のテストは、テスト対象が出来上がった後に実行するものですから、単体テストではテスト対象のソースコードを作成した後に実行することになります。先ほどのxUnitを使った場合、ソースコードとは別にテスト用のソースコード(以下、テストコード)を作成する必要があるため、手順は以下のようになります。
しかし、単体テストの場合は、ソースコードの作成よりも先にテストを実行する「テストファースト」と呼ばれる方法で進めることもできます。先にテストを実行するといってもピンとこないかもしれませんが、ソースコードが未完成の状態でテストをわざと失敗し、テストが成功するようにソースコードを完成させていくという手法です。この場合の手順は以下のようになります。
この手法では、テストコードを先に作ることで正しい仕様を確認し、さらに無駄のないソースコードを実装できるというメリットがあります。ただし、テスト対象もできていないのにテストコードを先に書くというのは慣れないとなかなかうまくいきませんので、初めて単体テストをする人が、いきなりテストファーストでやってみるというのはあまりお勧めしません。
実際には、「ソースコード作成」「テストコード作成」「テスト実行」の3つの作業を細かいサイクルで回して、テストが通るようなソースコードを完成させていくことで、効率よく品質の高いソースコードを実装することができるでしょう[1]。
それでは、次からは、Javaのテスティングフレームワークである「JUnit」を使った単体テストの実行方法について見ていきましょう。
JUnitとは
JUnitはJava用のテスティングフレームワークで、オープンソースで提供されており、Eclipseなどの統合開発環境にもデフォルトで同梱されています。
JUnitの機能
先ほども説明した通り、テスティングフレームワークを使う場合は、テストコードを作成する必要があります。JUnitが提供する機能には以下のものがあります。
- テストコードを記述するためのライブラリ
- テストコードの実行
- テスト結果の表示
JUnitのメリット・デメリット
これらのJUnitの機能の恩恵として、さまざまなメリットが得られます。代表的なものを挙げてみましょう。
- 統一された方法で効率よくテストを実行することができる
- 一度テストコードを作成すれば、簡単に回帰テストを実施することができる
- テストコードは、どのようなテストが実施されたかの証拠(エビデンス)となる
その一方で、テストコードを作成するための工数がかかることがデメリットとなります。ただし、先ほど挙げた通り、回帰テストの工数を削減できるメリットがありますので、単体テストだけでなく後工程でもうまく使いこなせば、全体としては工数削減につながるでしょう。
JUnitを使った単体テスト手順
では、第3回と同じサンプルコードに対して、実際にJUnitを利用してテストを実施してみましょう(リスト1)。
なお、今回は以下の実行環境を前提とします。Eclipseのインストール方法はページ数の都合により省略しますので、関連する書籍やWebサイト等を参考にしてください。
- 実行環境:
- Eclipse3.3.2(Pleiades All in Oneを利用)
JUnit3.8.1(Eclipseに同梱)
テストコードの作成
テストコードには、JUnitの実行対象となるテストメソッドを実装します。このテストメソッドには、テストケースの内容、すなわち「どういう入力を与えたときに、どういう結果が期待されるか」を確認するための実装をします。ここでは、doSample()メソッドに対して、
- 入力引数param:
abz
- 戻り値(配列):
{true, true}
となるテストケースの実装例を見てみましょう。テストメソッドの実装内容は、「テスト対象メソッドに引数を与えて実行する」部分と「実行結果を検証する」部分から成り、リスト2のようになります。
実行結果の検証部分で使用しているassertTrue()メソッドは、引数に与えた値がtrueかどうかを検証するためのものです。JUnitでは、他にも2つの引数の値が等しいかどうかを検証するassertEquals()メソッドなどさまざまな検証用メソッドが用意されており、期待通りの結果になっているかどうかが確認できます。
JUnitの実行
作成したテストコードをJUnitで実行することで、テストが成功したか失敗したかを確認することができます。JUnitはEclipse上ではメニューから容易に実行することができ、実行後の結果もEclipse上に表示されます。テストが成功すれば緑、失敗すれば赤い色のバーが表示されます(図1)。
カバレッジ計測ツールでカバレッジを測定する
JUnitを使ってテストをすれば、テスト対象のソースコードにバグがあるかどうかがわかりますが、実施したテストが十分かどうかまではわかりません。そのテストの十分性を測るためのひとつの手段が「カバレッジ[2]」で、カバレッジ計測ツールを使うことにより、JUnitの実行時にテスト対象のソースコードがどれくらい実行されたかを確認できます。
たとえば、カバレッジ計測ツールEMMAのEclipseプラグイン版であるEclEmmaを使ってカバレッジを計測すると、図2のようになります。この図で、緑色になっている行はテストで実行された行、赤い色の行は未実行の行を示しています。たいていの場合、未実行の行はテストが漏れている部分と判断できますので、そこを実行するようなテストケースを追加することで、より網羅性の高いテストが実行できます。ただし、未実行の行は実は必要のないコードだったということもありますので、結果を正しく見極める必要があります。また、使い方によっては、網羅率を上げることが目的になってしまいますので、注意しましょう。
まとめ
単体テストは非常に多くの工数がかかるため、省略して次のテスト工程に進んでしまう開発現場をよく見かけます。しかし、正しく単体テストを実施すれば、多くのバグを発見して品質を確保できると同時に、後工程での手戻りも減らすことができます。バグは早めに見つけて直してしまうに越したことはありません。そのために、今回紹介したプロセスやツールを参考にして、効率よく単体テストを実行しましょう。