1. テスト可能なコードを書く
まず、ビジネス ロジックをフォームのコード ビハインドに記述するのをやめます。それはその場所ではありません。そこでは適切にテストできません。実際、フォーム自体をテストする必要はまったくありません。これは、ユーザー インタラクションに応答し、それらのアクションに応答する責任をテスト可能な別のクラスに委任する、非常に単純なビューである必要があります。
どうやってそれをしますか?Model-View-Controller パターンに慣れることは、良い出発点です。
イベントまたはインターフェイスのいずれかを取得し、両方を取得することはないため、VBA で完全に実行することはできませんが、かなり近づけることはできます。テキスト ボックスとボタンを持つ次の単純なフォームを考えてみましょう。
フォームのコード ビハインドでは、TextBox の値をパブリック プロパティにラップし、関心のあるイベントを再発生させます。
Public Event OnSayHello()
Public Event AfterTextUpdate()
Public Property Let Text(value As String)
Me.TextBox1.value = value
End Property
Public Property Get Text() As String
Text = Me.TextBox1.value
End Property
Private Sub SayHello_Click()
RaiseEvent OnSayHello
End Sub
Private Sub TextBox1_AfterUpdate()
RaiseEvent AfterTextUpdate
End Sub
次に、操作するモデルが必要です。ここでは、 という名前の新しいクラス モジュールを作成しましたMyModel
。ここに、テストするコードがあります。当然、ビューと同様の構造を共有していることに注意してください。
Private mText As String
Public Property Let Text(value As String)
mText = value
End Property
Public Property Get Text() As String
Text = mText
End Property
Public Function Reversed() As String
Dim result As String
Dim length As Long
length = Len(mText)
Dim i As Long
For i = 0 To length - 1
result = result + Mid(mText, (length - i), 1)
Next i
Reversed = result
End Function
Public Sub SayHello()
MsgBox Reversed()
End Sub
最後に、コントローラーがすべてを結び付けます。コントローラーはフォーム イベントをリッスンし、変更をモデルに伝え、モデルのルーチンをトリガーします。
Private WithEvents view As Form_Form1
Private model As MyModel
Public Sub Run()
Set model = New MyModel
Set view = New Form_Form1
view.Visible = True
End Sub
Private Sub view_AfterTextUpdate()
model.Text = view.Text
End Sub
Private Sub view_OnSayHello()
model.SayHello
view.Text = model.Reversed()
End Sub
これで、このコードは他のモジュールから実行できます。この例では、標準モジュールを使用しました。私が提供したコードを使用してこれを自分で構築し、機能することを確認することを強くお勧めします。
Private controller As FormController
Public Sub Run()
Set controller = New FormController
controller.Run
End Sub
それで、それは素晴らしいことですが、それはテストと何の関係があるのでしょうか?! 友よ、それはテストと関係があります。私たちが行ったことは、コードをテスト可能にすることです。私が提供した例では、GUI をテストしようとする理由はまったくありません。本当にテストする必要があるのは、model
. そこにすべての真の論理があります。
では、ステップ 2 に進みます。
2. 単体テスト フレームワークを選択する
ここには多くのオプションはありません。ほとんどのフレームワークでは、COM アドイン、多数のボイラー プレート、奇妙な構文、コメントとしてのテストの記述などをインストールする必要があります。利用可能なものの公正な要約を提供します。
単位
- アクセスでのみ機能します。
- コメントとコードの奇妙なハイブリッドとしてテストを書く必要があります。(コメント部分のインテリセンスはありません。
- ただし、これらの奇妙に見えるテストを作成するのに役立つグラフィカル インターフェイスがあります。
- このプロジェクトは 2013 年以降更新されていません。
VB Lite Unit
個人的に使ったとは言えません。公開されていますが、2005 年以降更新されていません。
xlUnit
xlUnit は悪くはありませんが、良くもありません。それは不格好で、定型コードがたくさんあります。これは最悪の最善ですが、Access では機能しません。それで、それは出ました。
独自のフレームワークを構築する
私はそこにいて、それをしました。おそらくほとんどの人が入りたいと思っている以上のものですが、ネイティブ VBA コードで単体テスト フレームワークを構築することは完全に可能です。
Rubberduck VBE アドインのユニット テスト フレームワーク
免責事項: 私は共同開発者の 1 人です。
私は偏見がありますが、これは群を抜いて私のお気に入りです。
- 定型コードはほとんどまたはまったくありません。
- インテリセンスが利用可能です。
- プロジェクトはアクティブです。
- これらのプロジェクトのほとんどよりも多くのドキュメント。
- Access だけでなく、ほとんどの主要なオフィス アプリケーションで動作します。
- 残念ながら、これは COM アドインであるため、マシンにインストールする必要があります。
3. テストの作成を開始する
それでは、セクション 1 のコードに戻ります。実際にテストする必要があるコードはMyModel.Reversed()
関数だけです。それでは、そのテストがどのように見えるかを見てみましょう。(与えられた例ではラバーダックを使用していますが、これは単純なテストであり、選択したフレームワークに変換できます。)
'@TestModule
Private Assert As New Rubberduck.AssertClass
'@TestMethod
Public Sub ReversedReversesCorrectly()
Arrange:
Dim model As New MyModel
Const original As String = "Hello"
Const expected As String = "olleH"
Dim actual As String
model.Text = original
Act:
actual = model.Reversed
Assert:
Assert.AreEqual expected, actual
End Sub
良いテストを書くためのガイドライン
- 一度に 1 つのことだけをテストします。
- 優れたテストは、システムにバグが導入された場合、または要件が変更された場合にのみ失敗します。
- データベースやファイル システムなどの外部依存関係を含めないでください。これらの外部依存関係により、制御できない理由でテストが失敗する可能性があります。第二に、テストが遅くなります。テストが遅い場合は、実行しません。
- テストが何をテストしているかを説明するテスト名を使用します。長くなっても気にしないでください。説明的であることが最も重要です。
回答が少し長く、遅くなったことは承知していますが、一部の人々が VBA コードの単体テストを書き始めるのに役立つことを願っています。