VS 2008でProfessional版にも搭載されるようになった単体テスト機能。具体的にはどのようなテストが可能なのか?
Visual Studio 2005(以下、VS 2005)では上位エディションであるTeam Developerでのみ利用可能だった単体テスト機能が、Visual Studio 2008(以下、VS 2008)からは、Professional Editionでも利用可能になった。
VS 2008の1機能として導入されるほど単体テストが脚光を浴びるようになったのは、やはりアジャイル開発の普及だろう。アジャイルで開発する場合、単体の品質が非常に重要になる。また、リファクタリングなどで繰り返しテストが必要になるケースが多いため、テストを自動化するという考えが生まれ、単体テストの注目度はさらに増している。
本稿では、このVS 2008 Professional Editionに搭載されている単体テスト機能で何が可能になったのかを解説していく。
なお、本稿ではテスト・ファーストやアジャイル開発などの開発手法にはあまり深入りせず、あくまでもVS 2008の単体テスト機能に注目して解説していく。
単体テストとは、その名前のとおり、全体ではなく単体に対して行うテストのことである。とはいえ、「単体」の定義は厳密にされているわけではない。
例えば、汎用機の世界ではモジュールに対するテストを単体テストと呼んできたし、Webアプリケーションでは、ページに対するテストを単体テストと呼んだりする。Visual Studioにおける単体テスト機能では、メソッド、もしくはクラスに対するテストを単体テストと呼んでいる。
また、単体テストには2通りのテスト方法がある。
1つは、完全に入力値/出力値にのみ着目した「ブラックボックス・テスト」である。この方法は、コードの中身を意識せず、処理のあるべき姿を想定してテスト・コードを記述する。コードを実装した本人以外の第三者、もしくはコードを実装した本人が第三者的な視点でテスト・コードを記述する方法である。
実装に依存せずにテスト・コードを記述するため、より俯瞰(ふかん)した視点からコードを考えることができる。一般的に、詳細設計レベルの要件が満たされていることを確認する作業である。本稿で解説しているVS 2008 Professional Editionの単体テスト機能は、このブラックボックス・テストを行うためのものだ。
もう1つは、コードの内部構造に着目してテスト・コードを記述する「ホワイトボックス・テスト」である。この方法では、分岐やループなど、上から下に処理が流れるのではなく状態によって変化する部分に着目してテスト・コードを記述する。
この方法により単体テストを実施する場合、コード・カバレッジとの組み合わせが最適であるため、VS 2008の上位エディションであるVisual Studio Team System 2008を検討するか、サード・パーティ製品と組み合わせて使うことをお勧めする。本稿では、ホワイトボックス・テストについてはこれ以上触れない。
それではVS 2008の1機能としてIDEに統合された単体テスト機能は具体的にどのようなものなのか。実際に使いながら、まずはその基本的な機能から見ていこう。
■単体テスト・クラスを作成してみよう
VS 2008の単体テスト機能はIDEに統合されているため、非常に効率的にテストを作成することができる。まずは、単純な"足し算メソッド"を作って、そのテストを実施してみよう。
クラス・ライブラリを作成して、足し算メソッドを以下のように記述する。
次に、いま記述したクラスの中でマウスを右クリックし、メニューから[単体テストの作成]を選択する。
以下のような[単体テストの作成]ダイアログが表示されるので、単体テストを作成したいメソッドにチェックを入れて[OK]ボタンをクリックする。
これだけでテストの枠組みがテスト・プロジェクトとして作成され、現在のソリューションに追加される。次にテスト・コードを実際に書いていこう。
■テスト・コードを書いてみよう
単体テストを作成すると、以下のコードが自動生成される。
01: /// <summary>
02: ///足し算 のテスト
03: ///</summary>
04: [TestMethod()]
05: public void 足し算Test()
06: {
07: 四則演算 target = new 四則演算(); // TODO: 適切な値に初期化してください
08: int x = 0; // TODO: 適切な値に初期化してください
09: int y = 0; // TODO: 適切な値に初期化してください
10: int expected = 0; // TODO: 適切な値に初期化してください
11: int actual;
12: actual = target.足し算(x, y);
13: Assert.AreEqual(expected, actual);
14: Assert.Inconclusive("このテスト・メソッドの正確性を確認します。");
15: }
01: ''' <summary>
02: '''足し算 のテスト
03: '''</summary>
04: <TestMethod()> _
05: Public Sub 足し算Test()
06:
07: Dim target As 四則演算 = New 四則演算 ' TODO: 適切な値に初期化してください
08: Dim x As Integer ' TODO: 適切な値に初期化してください
09: Dim y As Integer ' TODO: 適切な値に初期化してください
10: Dim expected As Integer = 0; ' TODO: 適切な値に初期化してください
11: Dim actual As Integer
12: actual = target.足し算(x, y)
13: Assert.AreEqual(expected, actual)
14: Assert.Inconclusive("このテスト・メソッドの正確性を確認します。")
15: End Sub
コメントで「TODO」と書かれている部分が、これから実施しなくてはならない作業である。7行目は、テスト対象の足し算メソッドを含むクラスをインスタンス化しているが、このクラスではコンストラクタのパラメータがないため、変更せずにこのまま使用する。もし、コンストラクタのパラメータによってメソッドの処理が変わる場合には、ここで適切な値を渡す必要がある。
8〜9行目では、メソッドに渡す引数を初期化している。ここではテストを実施するために適切な値で初期化するようにする。10行目は、expectedという変数名からも分かるように、期待する戻り値である。あらかじめ、期待する値で初期化しておく。11行目はactual、つまり実際の戻り値を受け取る変数である。12行目で実際にメソッドを実行して、13行目で期待値と実際の値が一致しているかどうかを判定している。
14行目は、Inconclusiveというメソッドが呼ばれているが、これはテスト・メソッドが実装されていない状態を表すものである。この記述があると、単体テストは失敗する。これは、実装を忘れていたテスト・メソッドの実行で、テストがパスされることを防ぐ役割を果たしている。テスト・コードの実装が終わった時点で、この行を削除することで、正しく単体テストを実施できるようになる。
以下にテスト・コードを記述したテスト・メソッドを示す。
01: /// <summary>
02: ///足し算 のテスト
03: ///</summary>
04: [TestMethod()]
05: public void 足し算Test()
06: {
07: 四則演算target = new四則演算();
08: int x = 5;
09: int y = 3;
10: int expected = 8;
11: int actual;
12: actual = target.足し算(x, y);
13: Assert.AreEqual(expected, actual);
14: }
01: ''' <summary>
02: '''足し算 のテスト
03: '''</summary>
04: <TestMethod()> _
05: Public Sub 足し算Test()
06:
07: Dim target As 四則演算 = New 四則演算
08: Dim x As Integer = 5
09: Dim y As Integer = 3
10: Dim expected As Integer = 8
11: Dim actual As Integer
12: actual = target.足し算(x, y)
13: Assert.AreEqual(expected, actual)
14: End Sub
■テスト・コードを実行してみよう
テスト・プロジェクトを開いていると、[テスト ツール]ツールバーが表示されるので、ここからテストの実行を開始できる([テスト]メニューからも実行可能)。テストのデバッグを実行すると、テスト・コードにブレークポイントを設定して、デバッグを行うことができる。
テストを実行すると、[テスト結果]ウィンドウに進ちょく状況が表示された後、テストの実施結果が表示される。
そして、テストが成功すると緑のチェック・アイコンが、失敗すると赤い[×]アイコンが表示される。また、Assert.Inconclusiveメソッドを残したままにしている場合、オレンジ色の[?]アイコンが表示される。
テストに失敗した場合、[テスト結果]ウィンドウにもエラー原因が表示されるが、その行をダブルクリックすることで、より詳細なエラー情報を表示できる。
書いたテスト・コードを試しに実行してみたい場合など、すべてのテストではなく一部だけを実行したい場合には、[テスト ビュー]ウィンドウを開き(メニューの[テスト]−[ウィンドウ]−[テスト ビュー]で表示される)、実施したいテストを選択してから、([テスト ビュー]ウィンドウの)ツールバー部分にある[選択範囲の実行]または、[選択範囲のデバッグ]をクリックするとよい。
■テスト・コードを見てみよう
ご覧いただいたとおり、テスト・コードを記述し、メソッドが正しく動作するかどうかを確認するというのが、基本的なテストの機能である。
では、テスト・コードについてもう少し深く見てみよう。以下がテスト・クラスの全体像になる。
01: using 計算;
02: using Microsoft.VisualStudio.TestTools.UnitTesting;
03: namespace TestProject1
04: {
05: /// <summary>
06: ///四則演算Test のテスト クラスです。すべての
07: ///四則演算Test 単体テストをここに含めます
08: ///</summary>
09: [TestClass()]
10: public class Class1Test
11: {
〜 TestContextの記述は省略 〜
12: /// <summary>
13: ///足し算 のテスト
14: ///</summary>
15: [TestMethod()]
16: public void 足し算Test()
17: {
18: /// <省略> ///
19: }
20: }
01: Imports 計算
02: Imports Microsoft.VisualStudio.TestTools.UnitTesting;
03:
04:
05: ''' <summary>
06: '''四則演算Test のテスト クラスです。すべての
07: '''四則演算Test 単体テストをここに含めます
08: '''</summary>
09: <TestClass()> _
10: Public Class 四則演算Test
11:
〜 TestContextの記述は省略 〜
12: ''' <summary>
13: '''足し算 のテスト
14: '''</summary>
15: <TestMethod()> _
16: Public Sub 足し算Test()
17:
18: ''' <省略> '''
19: End Sub
20: End Class
まず、1行目でテスト対象のクラスを含む名前空間がusing(VBでは、Imports)ディレクティブで宣言されている。
次に、9行目でテスト・クラスの前に「TestClass」属性、15行目でテスト・メソッドの前に「TestMethod」属性が付与されていることが分かる。これらの属性を付与することで、テスト・メソッドとして動作するようになる。TestMethod属性のほかにも、さまざまなテストの属性が提供されているが、これについては後半で紹介する。
Copyright© Digital Advantage Corp. All Rights Reserved.