VBAに単体テストの考え方を取り入れるには、処理をFunctionに小分けして、テスト専用のSubで結果を確認するだけです。難しい専用ツールは不要で、MsgBox や Debug.Print を使えばすぐに始められます。
この記事では、次の内容を順番に解説します。
- 単体テストとは何か(VBAでの考え方)
- テスト用プロシージャの作り方
- Debug.Printを使ったログ確認
- 複数パターンのテストのまとめ方
- 実務でよく使うテストのパターン例
単体テストとは何かを理解するには?
単体テスト(ユニットテスト)とは、プログラムの「部品」ごとに正しく動くかを確認するテストのことです。マクロ全体を一気に動かして「うまくいった/いかなかった」で判断するのではなく、小さな処理単位ごとに「この部分は正しい」と確かめながら組み上げる考え方です。
VBAに単体テストの考え方が向いている理由は次の3つです。
- 処理をFunctionに分けやすい:VBAは複数のプロシージャやFunctionで構成できるため、テスト単位を作りやすい。
- 結果がシートで目視確認できる:Excelというシートという「見える場所」があるので、期待値と実際の値を比べやすい。
- 確認マクロを作るだけで導入できる:専用のテストフレームワークがなくても、
MsgBoxやDebug.Printだけで始められる。
テスト用プロシージャを作るには?
まず、テスト対象となるFunctionを用意します。次の例は価格に消費税10%を加算して返す関数です。
Function AddTax(price As Double) As Double
AddTax = price * 1.1
End Function
この関数が正しく動くかを確認するテスト用Subを別に作ります。
Sub Test_AddTax()
Dim result As Double
result = AddTax(1000)
If result = 1100 Then
MsgBox "OK:AddTaxは正常に動作しています。"
Else
MsgBox "NG:AddTaxの結果が想定外です → " & result
End If
End Sub
ポイントは「期待する値(1100)」と「実際の結果(result)」を比較していることです。このパターンさえ覚えれば、どんなFunctionでもテストできます。
| テストの要素 | 内容 |
|---|---|
| 入力値 | テストに使う引数(例:1000) |
| 期待値 | 正しく動いたときの結果(例:1100) |
| 実際の結果 | Functionが返した値(result) |
| 判定 | 期待値 = 実際の結果 → OK / 違う → NG |
Debug.Printでログを確認するには?
毎回 MsgBox を使うと「OK」を押す手間がかかります。複数のテストをまとめて実行したい場合は Debug.Print を使うと便利です。結果はVBEの「イミディエイトウィンドウ」(Ctrl+G)に出力されます。
Sub Test_AddTax_Log()
Dim result As Double
result = AddTax(200)
If result = 220 Then
Debug.Print "Test_AddTax(200):OK"
Else
Debug.Print "Test_AddTax(200):NG → " & result
End If
End Sub
実行後にイミディエイトウィンドウを確認すると「Test_AddTax(200):OK」のように表示されます。MsgBox と違い、クリックせずに複数の結果をまとめて確認できます。
複数パターンをまとめてテストするには?
境界値や特殊な入力(0・負の数・大きな値)でも正しく動くかを確認しておくと、本番で予期しないエラーが起きにくくなります。
Sub Test_AddTax_All()
' 通常ケース
Debug.Print "100 → "; AddTax(100) ' 期待値:110
' ゼロ
Debug.Print "0 → "; AddTax(0) ' 期待値:0
' 負の数
Debug.Print "-100 → "; AddTax(-100) ' 期待値:-110
' 大きな値
Debug.Print "10000 → "; AddTax(10000) ' 期待値:11000
End Sub
さらに判定まで自動化したい場合は次のようにまとめます。
Sub Test_AddTax_Auto()
Dim passCount As Long
Dim failCount As Long
' テストケースを配列で管理
Dim inputs(3) As Double
Dim expects(3) As Double
inputs(0) = 100: expects(0) = 110
inputs(1) = 0: expects(1) = 0
inputs(2) = -100: expects(2) = -110
inputs(3) = 10000: expects(3) = 11000
Dim i As Long
For i = 0 To 3
If AddTax(inputs(i)) = expects(i) Then
Debug.Print "OK:入力=" & inputs(i)
passCount = passCount + 1
Else
Debug.Print "NG:入力=" & inputs(i) & " 結果=" & AddTax(inputs(i)) & " 期待=" & expects(i)
failCount = failCount + 1
End If
Next i
Debug.Print "---"
Debug.Print "合計:OK=" & passCount & " / NG=" & failCount
End Sub
実務でよく使うテストパターンとは?
単体テストが特に効果を発揮するのは、次のような実務でよく使う処理です。
文字列処理のテスト
' テスト対象:文字列の長さチェック関数
Function CheckLength(txt As String) As String
If Len(txt) > 10 Then
CheckLength = "長すぎます"
ElseIf Len(txt) = 0 Then
CheckLength = "未入力です"
Else
CheckLength = "OK"
End If
End Function
' テスト用プロシージャ
Sub Test_CheckLength()
Debug.Print CheckLength("") ' 期待値:未入力です
Debug.Print CheckLength("abc") ' 期待値:OK
Debug.Print CheckLength("12345678901") ' 期待値:長すぎます(11文字)
End Sub
日付処理のテスト
' テスト対象:当月かどうか判定する関数
Function IsCurrentMonth(targetDate As Date) As Boolean
IsCurrentMonth = (Year(targetDate) = Year(Date) And Month(targetDate) = Month(Date))
End Function
' テスト用プロシージャ
Sub Test_IsCurrentMonth()
Debug.Print IsCurrentMonth(Date) ' 期待値:True(今日)
Debug.Print IsCurrentMonth(DateAdd("m", -1, Date)) ' 期待値:False(先月)
Debug.Print IsCurrentMonth(DateAdd("m", 1, Date)) ' 期待値:False(来月)
End Sub
セルの値を使った処理のテスト
' テスト対象:セルの値が数値かどうかチェックする関数
Function IsValidScore(val As Variant) As Boolean
If IsNumeric(val) Then
If val >= 0 And val <= 100 Then
IsValidScore = True
Else
IsValidScore = False
End If
Else
IsValidScore = False
End If
End Function
' テスト用プロシージャ
Sub Test_IsValidScore()
Debug.Print IsValidScore(80) ' 期待値:True
Debug.Print IsValidScore(0) ' 期待値:True(境界値)
Debug.Print IsValidScore(100) ' 期待値:True(境界値)
Debug.Print IsValidScore(101) ' 期待値:False(範囲外)
Debug.Print IsValidScore("abc") ' 期待値:False(文字列)
Debug.Print IsValidScore("") ' 期待値:False(空白)
End Sub
まとめ
- 単体テストの考え方:処理を小さなFunctionに分け、テスト専用のSubで「入力→期待値→実際の結果」を比較する。
- MsgBox:1つの処理を確認するシンプルな方法。
- Debug.Print:複数のテストをまとめて実行し、イミディエイトウィンドウで確認する方法。クリック不要で効率的。
- 複数パターンのテスト:通常ケース・ゼロ・負の数・境界値を用意しておくと本番での予期しないエラーを防げる。
- 実務での使いどころ:文字列チェック・日付処理・セル値の検証など、繰り返し使うFunctionほどテストの効果が高い。
よくある質問
テスト用のSubはどこに書けばいいですか?
本番のコードとは別の標準モジュールを作って、そこにまとめて書くのがおすすめです。モジュール名を「Test_Module」などにしておくと、本番コードと区別しやすくなります。リリース前にテスト用モジュールだけ削除するか、非表示にすることもできます。
SubではなくFunctionにする基準は何ですか?
「値を返す処理」はFunctionにするのが基本です。例えば計算・判定・文字列の変換など、「何かを入れると何かが返ってくる」処理はFunctionが向いています。Subは「保存する」「シートを更新する」など副作用のある処理に使います。Functionにしておくとテストがしやすくなります。
Debug.Printの結果はどこで確認できますか?
VBEを開き(Alt+F11)、メニューの「表示」→「イミディエイトウィンドウ」か Ctrl+G で開けます。マクロを実行するとそこに出力されます。イミディエイトウィンドウは画面下部に表示されます。
テストを書く手間が増えませんか?
最初は手間に感じますが、マクロの規模が大きくなるほどテストの効果が出ます。特に「仕様を変えたとき」「他の人が使うとき」に、テストがあると修正後の動作確認が一瞬で終わります。小さなFunctionを1つ作るたびに3〜4行のテストSubを追加する習慣をつけると無理なく続けられます。
マクロ全体のテストはどうすればいいですか?
全体の流れをテストする場合は、テスト用のシートやデータを別途用意して実行するのが現実的です。本番データを直接使わず、テスト用の入力データ・期待する出力結果を用意しておいて、マクロ実行後にセルの値を確認します。本番環境とテスト環境をシートで分けておくと安全に繰り返しテストできます。
動画で学びたい方へ
「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。
VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。



