J'ai pris une page de Doctest de Python et mis en œuvre une procédure DocTests dans Access VBA. Il ne s'agit évidemment pas d'une solution de test unitaire à part entière. Elle est encore relativement jeune, et je ne pense pas avoir résolu tous les bogues, mais je pense qu'elle est suffisamment mûre pour être diffusée dans la nature.
Il suffit de copier le code suivant dans un module de code standard et d'appuyer sur F5 à l'intérieur du module pour le voir à l'œuvre :
'>>> 1 + 1
'2
'>>> 3 - 1
'0
Sub DocTests()
Dim Comp As Object, i As Long, CM As Object
Dim Expr As String, ExpectedResult As Variant, TestsPassed As Long, TestsFailed As Long
Dim Evaluation As Variant
For Each Comp In Application.VBE.ActiveVBProject.VBComponents
Set CM = Comp.CodeModule
For i = 1 To CM.CountOfLines
If Left(Trim(CM.Lines(i, 1)), 4) = "'>>>" Then
Expr = Trim(Mid(CM.Lines(i, 1), 5))
On Error Resume Next
Evaluation = Eval(Expr)
If Err.Number = 2425 And Comp.Type <> 1 Then
'The expression you entered has a function name that '' can't find.
'This is not surprising because we are not in a standard code module (Comp.Type <> 1).
'So we will just ignore it.
GoTo NextLine
ElseIf Err.Number <> 0 Then
Debug.Print Err.Number, Err.Description, Expr
GoTo NextLine
End If
On Error GoTo 0
ExpectedResult = Trim(Mid(CM.Lines(i + 1, 1), InStr(CM.Lines(i + 1, 1), "'") + 1))
Select Case ExpectedResult
Case "True": ExpectedResult = True
Case "False": ExpectedResult = False
Case "Null": ExpectedResult = Null
End Select
Select Case TypeName(Evaluation)
Case "Long", "Integer", "Short", "Byte", "Single", "Double", "Decimal", "Currency"
ExpectedResult = Eval(ExpectedResult)
Case "Date"
If IsDate(ExpectedResult) Then ExpectedResult = CDate(ExpectedResult)
End Select
If (Evaluation = ExpectedResult) Then
TestsPassed = TestsPassed + 1
ElseIf (IsNull(Evaluation) And IsNull(ExpectedResult)) Then
TestsPassed = TestsPassed + 1
Else
Debug.Print Comp.Name; ": "; Expr; " evaluates to: "; Evaluation; " Expected: "; ExpectedResult
TestsFailed = TestsFailed + 1
End If
End If
NextLine:
Next i
Next Comp
Debug.Print "Tests passed: "; TestsPassed; " of "; TestsPassed + TestsFailed
End Sub
Copier, coller et exécuter le code ci-dessus à partir d'un module nommé Module1 donne :
Module: 3 - 1 evaluates to: 2 Expected: 0
Tests passed: 1 of 2
Quelques remarques rapides :
- Il n'a pas de dépendances (lorsqu'il est utilisé à partir d'Access).
- Il utilise
Eval
qui est une fonction dans le modèle d'objet Access.Application ; cela signifie que vous pourrait l'utiliser en dehors d'Access, mais cela nécessiterait de créer un objet Access.Application et de qualifier complètement l'objet Access.Application. Eval
appels
- Il y a quelques idiosyncrasies associées aux
Eval
être conscient de
- Il ne peut être utilisé que pour les fonctions qui renvoient un résultat tenant sur une seule ligne
Malgré ses limites, je pense qu'il offre un bon rapport qualité-prix.
Editer : Voici une fonction simple avec des "règles doctest" que la fonction doit satisfaire.
Public Function AddTwoValues(ByVal p1 As Variant, _
ByVal p2 As Variant) As Variant
'>>> AddTwoValues(1,1)
'2
'>>> AddTwoValues(1,1) = 1
'False
'>>> AddTwoValues(1,Null)
'Null
'>>> IsError(AddTwoValues(1,"foo"))
'True
On Error GoTo ErrorHandler
AddTwoValues = p1 + p2
ExitHere:
On Error GoTo 0
Exit Function
ErrorHandler:
AddTwoValues = CVErr(Err.Number)
GoTo ExitHere
End Function