Visual Basicで単体テストする方法

Visual Basic単体テストする方法を覚え書きとして記しておきます。

コツは以下の3点です。

  1. 単体テストの対象は、モジュールではなく、クラスである
  2. 既存のソリューションの中に、テスト用のプロジェクトを新たに作る
  3. テスト用のプロジェクトでテスト対象のプロジェクトを参照設定する

本記事は、試行錯誤の結果を記していますので、間違いがあるかもしれません。お気付きの点がありましたら、ご指摘ください。

具体的な方法をすぐに知りたい方は、前座をとばして、こちらからどうぞ。

Visual Basicで単体テストをする方法が良くわからない

恥ずかしながら、僕は今まで、単体テストをしながらプログラムを開発したことがありません。
しかし、昨今、単体テストが必須というムードになってきています。
そこで、そろそろ流れに乗ってみようかと思うようになりました。

僕がよく使う言語は、Visual Basicです。ExcelのVBAに始まり、VB6を経てVisual Basicにたどり着いたパターンです。Visual Basicは初心者にとって、取り組みやすい言語だと思います。

ところが、「Visual Basic 単体テスト」として検索すると、「Visual Studio 単体テスト」の結果ばかり返されてきます。

確かに、Visual BasicはVisual Studioに含まれているから間違いではありません。でも、リンクをクリックすると、使われている言語はC#なんです。

僕の知りたいのはVisual Basicなんだよ!と、言いたいです。

雰囲気を知るために、C#で単体テストをしてみる

でも、先ずは雰囲気を知るために、C#のチュートリアルを試してみることにしました。

C# 単体テスト チュートリアル - Visual Studio (Windows)
マネージド コード用の Microsoft 単体テスト フレームワークと Visual Studio テスト エクスプローラーを使用して一連の単体テストを作成、実行、およびカスタマイズする方法について説明します。

紆余曲折はあったものの、何とか一通りを終えました。
このチュートリアルから得たことは2つありました。

1)単体テストは分岐の数だけAssert文が必要である

僕は単体テストという言葉から、関数1つに対して単体テスト1つが対応していると思っていました。
また、戻り値を持たないサブルーチン(void関数)のテストの仕方が解りませんでした。

でも、このチュートリアルで解りました。Debitという払い戻しのサブルーチンは、Balanceというプロパティを別途呼び出して、その値をAssert文でテストすれば良いのです。

ただし、1つのAssert文で全てがテストできるわけではありません。If文があれば、分岐のそれぞれについてテストが必要です。
つまり、Assert文は関数の数だけ必要というより、分岐の数だけ必要だということです。

2)例外に対するテストも必要

僕は、例外処理を使ったコードを書いたことがほとんどありませんでした。
エラー内容を戻り値に含めて返していたからです。

でも、チュートリアルには例外処理のテスト方法が書かれていました。
普通は、世間の動向に従って、例外をスローするコードを書くべきなのでしょう。

その例外のテストコードは以下のようにさらっと書かれています。

Assert.ThrowsException<System.ArgumentOutOfRangeException>(() => account.Debit(debitAmount));

これは、C#のコードです。Visual Basicで「() =>」をどのように表現するのでしょうか?こういうところを一行補足するだけで、Microsoftのドキュメントが劇的にフレンドリになってくれると思うのは僕だけでしょうか?

単体テストとは単体クラスに対するテストと理解した

具体的なコードを示す前に、もう一言だけ述べさせてください。

単体テストの「単体」とは結局何でしょうか?

僕が思うには、「単体クラス」に対するという意味だと思います。

Visual Basicの単体テストが実行できる条件をいろいろと試してみてこの考えに至りました。

Visual Basicでは、標準モジュールがあります。標準モジュールは、インスタンス化しないで使用することができるため、クラスとは異なります。この標準モジュールの単体テストが用意されていない(?)ことが、Visual Basicの単体テストを紹介するサイトが少ない理由に思えます。

Visual Basicの単体テスト

ここではVisual Studio 2019のVisual Basicを使います。
割り算を実行するclsDivisionクラスのdiv関数をテストすることとします。

・Visual Basic 2019を立ち上げる
・「新しいプロジェクトの作成」をクリック

新しいプロジェクトの作成

新しいプロジェクトの作成

・右上の3つのコンボボックスで、「Visual Basic」「Windows」「コンソール」を選ぶ → 「コンソール アプリ(.NET Framework)」を選ぶ → 「次へ」
※「コンソール」を選んだのは、ここではフォームを使う必要がないからです。フォームを使う必要がある場合は、「デスクトップ」を選んでから「Windowsフォームアプリケーション(.NET Framework)」等を選んで下さい。

・プロジェクト名を「division」とし、場所を適当に選ぶ→ 「作成」

新しいプロジェクトを構成します

新しいプロジェクトを構成します

・「ソリューションエクスプローラ」の「division」を右クリック → 「追加」 → 「クラス」

新しい項目の追加

新しい項目の追加

・「クラス」アイコンを選択 → 名前に「clsDivision」と入力 → 追加

clsDivision.vb

clsDivision.vb

・clsDivisionのエディタが開くので、以下のdiv関数を含むコードをコピー&ペーストする

Public Class ClsDivision
    Public Function Div(ByVal dblA As Double, ByVal dblB As Double) As Double
        ' 割る数が0の場合は例外処理
        If dblB = 0 Then Throw New ArgumentException("denominator")
        ' 商を返す
        Return dblA / dblB
    End Function
End Class

・「ソリューションエクスプローラ」の「ソリューション’division’(1/1 プロジェクト)」を右クリック→「追加」→「新しいプロジェクト」

新しいプロジェクトを追加

新しいプロジェクトを追加

・一番右のコンボボックスから「テスト」を選ぶ→「単体テストプロジェクト(.NET Framework)」を選ぶ→「次へ」

新しいプロジェクトを構成します

新しいプロジェクトを構成します

・プロジェクト名を「TestDivision」と入力→場所を適当に選択(ここではdivisionプロジェクトフォルダとした)→「作成」

ソリューションエクスプローラのTestDivision

ソリューションエクスプローラのTestDivision

・「ソリューションエクスプローラ」の「TestDivision」の「参照」を右クリック→「参照の追加」
・左のメニューで「プロジェクト/ソリューション」を選ぶ→「division」のチェックボックスをチェック→「OK」
・次のコードをTestDivisionのUnitTest1.vbにコピー&ペーストする
※このコードは15÷3=5であることと、15÷0のとき、ArgumentExceptionが発生することを確認します

Imports System.Text
Imports Microsoft.VisualStudio.TestTools.UnitTesting

<TestClass()> Public Class UnitTest1

    <TestMethod()> Public Sub TestMethod1()
        Dim dblNumerator As Double = 15
        Dim dblDenominator As Double = 3
        Dim dblExpected As Double = 5
        Dim obj As New division.ClsDivision

        Assert.AreEqual(dblExpected, obj.Div(dblNumerator, dblDenominator))
        Dim dblDenominator0 As Double = 0
        Assert.ThrowsException(Of ArgumentException)(
            Sub()
                obj.Div(dblNumerator, dblDenominator0)
            End Sub)
    End Sub

End Class

・「表示」→「テストエクスプローラ」

テストエクスプローラ

テストエクスプローラ

・「テストエクスプローラ」の「▶マーク」をクリックしてテストを実行

・実行後に緑地のチェック(テスト成功)が入っていることを確認する
※TestMethod1の変数の値を変更して、テストが失敗することも確かめてみてください

まとめ

VB.netで単体テストする手順を示しました。
今後、僕がソフトウェアを作る際には、単体テストを取り入れていこうと思います。

ところで、結局、(標準)モジュールはどうやってテストするのでしょうか?
標準モジュールの関数を呼び出すクラスをテスト用に作るのでしょうか?それとも標準モジュールは使わない方向にシフトしていくべきなのかな。

 

 

コメント

タイトルとURLをコピーしました