BVUnitホームページ

BVUnitチュートリアル

BVUnit2を利用したユニットテストのチュートリアルです.

Step0.サンプルシナリオ

以下のようなプログラムを作成しようとしていると,仮定します.このプログラムは,標準Exeから利用されるファイルで,クラスファイルと標準モジュールファイルで提供される物とします.

ファイル

作成するファイル
ファイル名 モジュール名 説明
Vector.cls Vector ベクトルクラス
VectorUtil.bas VectorUtil ベクトル演算を定義したモジュール

公開するインタフェース

Vector
名前 型宣言 エラー 説明
Dimention : () -> Long = Property[r] - ベクトルの次元
Value : Long -> Double = Property[r/w] indexがおかしいと,エラー ベクトルの値

VectorUtil
名前 型宣言 エラー 説明
Add : Vector * Vector -> Vector = Function ベクトルの次元が異なるとエラー ベクトル同士の加算
CreateVector : Long -> Vector = Function 次元を指定するLongが0以下でエラー ベクトルを生成
Mul : Vector * Double -> Vector = Function - ベクトルにスカラーを乗算
Norm : Vector -> Double = Function - ベクトルのノルム
Normalize : Vector -> Vector = Function Norm=0でエラー 正規化したベクトルを返す

Step1.テストプロジェクトの作成

最初に,テスト用プロジェクトを作成します.ここでは,TestVectorとします.このステップは,テストプロジェクトにテストに必要なファイルを登録するところまでです.

プロジェクトの作成

標準Exeプロジェクトを新規作成します.

Step1.テストプロジェクトの作成

ファイルの追加

Form1がデフォルトで登録されていますが,不要なので削除します.また,Module1,Vector,VectorUtil,TEST_Vector,TEST_VectorUtilを追加します.Module1とVectorUtilは標準モジュールで,他は全てクラスモジュールです.

Step1.必要なファイルの登録

参照設定の設定と,スタートアップの変更

プロジェクトの参照設定で,「BVUnit2」を登録します.

Step1.テストプロジェクトの参照設定でBVUnit2を登録

さらに,プロジェクトのプロパティで,スタートアップを「Sub Main」に変更します.また,プロジェクト名もここでTestVectorに変更しておきましょう.(Form1を開放した時点で,スタートアップはSub Mainになっていますね・・・)

Step1.スタートアップを変更

プロジェクトの保存

ここまでで,一度プロジェクトとファイルを保存しましょう.ここでは,「VectorLib\tests」にVectorTest.vbp,Module1.bas,TEST_Vector.cls,TEST_VectorUtil.clsを,「VectorLib\Lib」にVector.cls,VectorUtil.basを保存することにします.

Step1.ファイルを保存

もちろん,ファイル名やファイルの配置は自由でかまいません.

Step2.テストの準備

Step2ではテストコードを記述する直前までの,おまじないに関して説明します.

Sub Main

とりあえず,Module1にSub Mainを用意しておきましょう.この時点では,コードは記述する必要はありません.

[Module1]

Sub Main

End Sub

BVUnit2.ITest

テストクラス−TEST_Vector,TEST_VectorUtil−には,BVUnit2.ITestをimplementsする必要があります.以下のように記述します.

[TEST_Vector,TEST_VectorUtil]

Implements BVUnit2.ITest

Private Sub ITest_Setup(ByVal ast_ As BVUnit2.IAssert)

End Sub

Private Sub ITest_Teardown()

End Sub

ITest_Setupは,テストを実行する前にコールされます.ITest_Teardownはテストが終了したあとにコールされます.ITest_Setupはテスト固有の初期化処理を実行するために用意してありますが,もう一つ重要な役割があります.BVUnit2.IAssertのast_を,テスト内に捕まえておくことです.ここでは,次のようにプログラムします.

[TEST_Vector, TEST_VectorUtil]

Implements BVUnit2.ITest

Private ast As BVUnit2.IAssert

Private Sub ITest_Setup(ByVal ast_ As BVUnit2.IAssert)
    Set ast = ast_
End Sub

Private Sub ITest_Teardown()

End Sub

astとするかm_astとするか,あるいは他の名前を使うかは,もちろんプログラマの自由ですが,テストであることを考えると,astと簡潔にすませるのが最適だと思います.メンバ変数をastとできるよう,Setupの仮引数にはast_と命名してあります.

テストでは,astを通じて,Assertionを行います.Assertionが真か偽かをBVUnitは判定し,テストが成功したか失敗したかを判断します.

BVunit2.TestSuite

このテストを実行できるよう登録しなくてはなりません.Sub Mainに次のように記述します.

Sub Main()
    BVUnit2.TestInGUI True, BVUnit2.CreateSuite("Test Vector suite", New TEST_Vector), _
                            BVUnit2.CreateSuite("Test VectorUtil suite", New TEST_VectorUtil)
End Sub

BVUnit2.TestInGUIは,引数として受け取ったテストスイートを実行対象としてテストを行う画面を表示します.一つ目の引数Trueは,ユーザーの指示を待って実行するかを決定するパラメータです.Falseを渡すと,画面表示と同時にすべてのテストスイートをテストし,結果を表示します.

BVUnit2.CreateSuiteはテストスイートオブジェクトを作成する関数です.一つ目の引数がテストスイートの名前になります.テストスイートには,複数のテストを登録できるので,VectorLibに含まれる二つのモジュールをスイートとして含むように,CreateSuite("Test VectorLib suite", New TEST_Vector, New TEST_VectorUtil)としてもかまいません.ここでは,上に示したコード例のようにプログラムしたとして進めます.

ここまでプログラムした時点で,実行してみると,次のような画面が表示されます.

Step2.テスト実行画面

まだテストを書いていないので,実行してもなにも表示されない・・・わけではないですね.

Step2.テスト実行画面2

## Tests Ran: 0
   | Passed: 0
   | Failed: 0
   | Error: 0
   | Skiped: 0

と,0個のテストが実行されたことが表示されます.これからテストを書かなくてはいけません.

インタフェースの記述

とりあえず,VectorとVectorUtilのインタフェースを記述します.次のようにしました.

[Vector]

Public Property Get Dimention() As Long

End Property

Public Property Get Value(ByVal index As Long) As Double

End Property

Public Property Let Value(ByVal index As Long, ByVal new_value As Double)

End Property
[VectorUtil]

Public Function CreateVector(ByVal dim_ As Long) As Vector

End Function

Public Function Add(ByVal vec1 As Vector, ByVal vec2 As Vector) As Vector

End Function

Public Function Mul(ByVal vec1 As Vector, ByVal f As Double) As Vector

End Function

Public Function Norm(ByVal vec1 As Vector) As Double

End Function

Public Function Normalize(ByVal vec1 As Vector) As Vector

End Function

テストファーストにしたがえば,テストを先に記述するべきなのですが,VBだとインタフェースを先に書いた方が便利なのでそうします.インタフェースがアレですと,コンパイルも通らないことですし.

テストの記述

それでは実際にテストコードを記述してみましょう.IAssertのテスト用APIを説明した後,実際に記述した後のテストコード例を示します.

テストするサブルーチン

BVUnit2では,ITestを実装したクラスのPublicなサブルーチンのうち,"Test"で名前が始まるものをテスト関数として認識します.例えば,次のようなサブルーチンはテスト関数として認識されます.

テスト関数の型はML風に書くところの「unit -> unit」となっています.引数ゼロ,返り値なしです.

エラーをチェックするサブルーチン

BVUnit2では,あるサブルーチンがエラーを発生することをテストすることができます.つまり,ある一連のプログラム片が特定の番号のエラーをRaiseすることをテストできます.ITestを実装したクラスのPublicなサブルーチンうち,"Err"で名前が始まるものが,エラーチェック関数として認識されます.名前の例は次にしめすリストの通り.

ByRef渡しのLongの値をパラメータとして利用します.実際のテストコードでは,ByRef e As Longとか書くのはだるいので,ByRefを省略し,さらにLongの値を代入できるVariant型としても良いので,eだけで問題ありません.

eには,発生して欲しいエラーの番号をプログラムがエラーを発生するまでに設定しておきます.

Public Sub ErrTest(e)
  e = 9

  'Err.Raise 10
  Err.Raise 9
End Sub

などとします.BVUnit2は,ErrTestをコールした際にエラーが発生すると(あるいはエラーが発生しなくても)eに渡した値とErr.Numberを比較し,等しかった場合テスト成功とします.

IAssert.Assert

IAssert.Assertの宣言は次のようになっています.

Public Sub Assert(ByVal result As Boolean, Optional Byval message As String = "")

resultがTrueの時テスト成功です.次のようにして利用します.

  ast.Assert v.Dimention = 3, "VectorUtil.CreateVector(3).Dimention == 3"

IAssert.AssertEqual

IAssert.AssertEqualの宣言は次のようになっています.

Public Sub AssertEqual(ByVal expected As Variant, ByVal actual As Variant, ByVal message As String = "")

expectedとactualが等しいとき,テスト成功です.ここで,等しいの意味がオーバーローディングされていることに注意してください.普通の値の場合,等値テストは「expected = actual」という式で行われます.expectedとactualがともに浮動小数点型の値の場合,等値テストは「Abs(expected - actual) <= Eps」という式で行われます.両方ともオブジェクトの場合は(本当は無視したいのですが),等値テストは「expected Is actual」という式で行われます.特にオブジェクトの比較には注意してください.これは基本的に役に立ちません.

  ast.Assert v.Dimention, 3, "Dimention of Vector"
  ast.Assert VectorUtil.Norm(v), 1.0, "|v| == 1.0"

MATSUMOTO Soutaro < soutaro@users.sourceforge.jp >
$Date: 2004-07-17 01:56:24 +0900 (Sat, 17 Jul 2004) $