2014年6月15日日曜日

VBAで手軽にTDDする。(Assert.basの使い方)

【概要】


VBAのユニットテスト用モジュール Assert.basを利用して、手軽にユニットテストする(テスト駆動開発;TDDする)方法についてまとめました。

「VBAで、手軽にユニットテストしたい」という方のお役に立てれば幸いです。

なお、「ユニットテストの仕方が分かれば、当然TDDの方法もわかるよな?」という雰囲気がするので、以下では、ユニットテストの方法を説明するのみに留め、具体的にVBAでTDDする方法までは説明していません。なんというタイトル詐欺。

【目次】

  • Assert.basとは
  • 導入手順
  • 使い方
    • ユニットテストの作成
    • ユニットテストの実行
    • 具体例

【Assert.basとは】


元カリスマ エクストリームVBAプログラマーの@igetaさんが作られたVBAライブラリ集(Ariawase)に収録されたライブラリの1つです。

『既存のユニットテスト用ツール(※1)が気軽には使いづらい』という問題を解決すべく、手軽に、かつ、必要十分なユニットテストができるように作られています。(作成の動機はたしかそんな感じだったような気がしますが、うろおぼえです。)

Assert.basは、3つのファイルをプロジェクトにインポートするだけで利用でき、導入が簡単です。また、WordやAccessでも利用可能な点で既存のツールに対して優れています。(※2)

※1 VBAUnit、VB Lite Unit、xlUnitなど。これらのツールについて詳しくは、VBA のユニットテスト - miauの避難所 が参考になります。
※2 Word2013で利用する場合、VBProjectプロパティ の 「Case "Microsoft Excel": ~」でコンパイルエラーが出るので、コメントアウトする必要がありました。(Accessに対応した行はコメントアウトしなくても大丈夫なので謎い)

【導入手順】

プロジェクトに、Ariawaseの中から以下の3つのファイルをインポートします。(ちなみに、なぜ3つ必要かと言うと、Assert.basが、Core.bas, Func.clsに依存しているためです。)
  • Assert.bas
  • Core.bas
  • Func.cls
具体的な手順としては、上記3つのファイルをAriawaseフォルダから、VBEにDrag&DropすればOKです。以下のような構成になればOKです。

【使い方】

ユニットテストの作成

  1. テスト用のクラスを作成する。
    1. テストしたいモジュールまたはクラス名の末尾に "Test" をつけたクラスを作成すると、分かり易くて良いかと思います。
      ※ モジュールではなくクラスを作成してください。お間違えないよう。
  2. テスト用のクラス内に、テストメソッドを作成する。
    1. メソッド名の末尾には "_Test" をつけてください。
完全に余談ですが、「Test」、「_Test」というSuffixについては、Assert.basの定義部(先頭から10、11行目)を書き換えれば変更可能です。

Assert.basに用意されているテストメソッドは、以下の通りです。
使い方は、Ariawaseに含まれるMonkeyTest.clsを参照するのが手っ取り早いと思います。
概要メソッド名
値がNullに一致IsNullVal
引数 expType で指定した型に一致IsInstanceOfTypeName
引数 expType で指定した型に一致しないIsNotInstanceOfTypeName
引数exp の値と一致AreEq
引数exp の値と一致AreEqual
引数exp の値と一致しないAreNotEq
引数exp の値と一致しないAreNotEqual
引数exp で指定した配列と一致AreEqualArr
引数exp で指定した配列と一致しないAreNotEqualArr
引数procのプロシージャは引数errnum のエラーが発生するIsErrMethod
引数funcのファンクションは引数errnum のエラーが発生するIsErrFunc

ユニットテストの実行

全テストを実行する場合

イミディエイトウィンドウ(「表示」→「イミディエイトウィンドウ」、または[Ctrl]+[G])で
  1. Assert.TestRunnerGenerate (テスト実行用コード(TestRunner)を生成)
  2. Assert.RunTest (TestRunnerを実行)
この後、同じテストを繰り返すのであれば Assert.RunTest のみ実行でOKです。
なお、テストクラスやメソッドを追加した場合は、Assert.TestRunnerClear (TestRunnerを削除)を実行した後に、上記手順を行ってください。

特定のテストクラスのみ実行する場合

  1. Assert.RunTestOf New テストクラス
だけでOKです。

具体例

Module1 に、2つの引数をとり足し算する addというプロシージャを作成し、
Module1Testというクラスに、addのテストメソッド(add_正常系_Test, add_異常系_Test)を作成します。


あとは、イミディエイトウィンドウでAssert.TestRunnerGenerateと入力してEnter、続けてAssert.RunTestと入力してEnterです。


ちなみに、実装を間違ってる場合は、以下のように実装ミスを示してくれます。


以上のように、VBAでも、超絶お手軽にユニットテストができるようになります。
Assert.basで、レガシーコードにドロップキック!