vbaでもtdd
DESCRIPTION
TDD on ExcelVBA DEMOsTRANSCRIPT
こんなTDDもありかもね
2013/07/27 てらひで
この資料は2013/07/27に行われたTDDBCTokyoの懇親会で行ったLTを再編成したものです
てらひで @terahide27
認定スクラムマスターアジャイルコーチアーキテクト
てらひで @terahide27
http://gigazine.net/news/20130601-anime-2013summer/
深夜アニメのカバレッジ90%以上
本題
翠田あい@AiMidorita
VBAでもTDD!
xUnit?
VBAUnitがあるんだなw
だけど今日は使いません
標準機能
Debug.Assert
やってみよう
Alt+F11
Excelを開いて、VBEditorを開きます
メニュー → 挿入→ 標準モジュール
Option ExplicitSub いちに2を加えると3になるべき()
Dim Calc As New CalcDebug.Assert Calc.Add(1, 2) = 3
End Sub サブプロシージャ名は数字から始められないので平仮名の「いち」
標準モジュールのテストにカーソルをあてて F5
黄色くなった!
クラスモジュールを修正(明白な実装)
Option Explicit
Function add(i1 As Integer, i2 As Integer) As Integer
add = i1 + i2End Function
Calc
仮実装は省略!
標準モジュールのテストにカーソルをあてて F5
白くなった!
ちょっとリファクタ。イミディェイトに表示
Option Explicit
Sub いちに2を加えると3になるべき()Dim Calc As New CalcDim actual As Integeractual = Calc.add(1, 2)Debug.Assert actual = 3Debug.Print actual
End Sub
テストスイートも作れる!
たぶん。。。
やってみた
クラスモジュールTestSuite.cls
を追加
Option Explicit
''usage''Sub allTest()'' Dim TestSuite As New TestSuite'''' With TestSuite'' .testAll'' '.testAll ("test") 'procedurePrefix'' '.testAll (procedurePrefix =:"test", modeulePrefix :="テスト")'' End With''''End Sub
Private Const VBEXT_CT_STDMODULE As Integer = 1
Public Sub testAll(Optional procedurePrefix As String = "", Optional modeulePrefix As String = "test")
Dim subProcedureNames As Collection 'Collection<String>Set subProcedureNames = getSubProcedureNames(modeulePrefix)Dim subProcedureName As StringDim v
For Each v In subProcedureNamessubProcedureName = vIf Not isEmpty(procedurePrefix) Then
If Not startWith(subProcedureName, procedurePrefix) ThenGoTo continue
End IfEnd If
Application.Run ThisWorkbook.Name & "!" & subProcedureName
continue:Next
End Sub
Private Function getSubProcedureNames(modeulePrefix As String) As Collection 'Collection<String>Dim modules As Collection 'Collection<VBComponent>Dim subProcedureNames As New Collection 'Collection<String>Dim VBComponent As ObjectSet modules = getModules(modeulePrefix)Dim vDim iDim subProcedureName As String
For Each v In modulesSet VBComponent = v
With VBComponent.CodeModule
For i = 1 To .CountOfLinessubProcedureName = .ProcOfLine(i, 0)If isEmpty(subProcedureName) Then
GoTo continueEnd IfIf contains(subProcedureNames, subProcedureName) Then
GoTo continueEnd If
subProcedureNames.add subProcedureName
continue:Next i
End WithNext
Set getSubProcedureNames = subProcedureNamesEnd Function
Private Function getModules(modeulePrefix As String) As Collection 'Collection<VBComponent>Dim col As New CollectionDim VBComponent As ObjectDim vFor Each v In ThisWorkbook.VBProject.VBComponents
Set VBComponent = vWith VBComponent
If .Type <> VBEXT_CT_STDMODULE ThenGoTo continue:
End IfIf Not startWith(.Name, modeulePrefix) Then
GoTo continue:End If
col.add VBComponent
End Withcontinue:
Next
Set getModules = colEnd Function
Private Function contains(col As Collection, value) As BooleanDim vFor Each v In col
If v = value Thencontains = TrueExit Function
End IfNext
End Function
Private Function isEmpty(s As String) As BooleanIf s = "" Then
isEmpty = TrueEnd If
End Function
Private Function startWith(s As String, prefix As String) As BooleanIf InStr(1, s, prefix) = 1 Then
startWith = TrueEnd If
End Function
さっきのモジュール名とサブプロシージャ名の先頭にtestを追加
標準モジュールのテストにカーソルをあてて F5
Sub allTest()Dim TestSuite As New TestSuite
With TestSuite.testAll ("test")
End WithEnd Sub
クリアしておきましょう
標準モジュールのテストにカーソルをあてて F5
Excelのメニュー→ファイル→オプション→セキュリティセンター
クリック
マクロの設定→VBAプロジェクトオブジェクトモデルへのアクセスを信頼する
注意!
この設定によりマクロウイルスに感染しても筆者は一切の責任を負いません
標準モジュールのテストにカーソルをあてて F5
実行されました
テストのサブプロシージャを追加して実行してみましょう!
Excelのメニュー→ファイル→オプション→セキュリティセンターの設定を戻しておきましょう
クリック
チェックをはずす