【发布时间】:2014-11-29 14:08:58
【问题描述】:
上下文
我在 VBA 中写了一点unit testing library,所以我可以像这样编写单元测试:
'@ExpectedError()
Public Sub TestCannotRegisterLoggerTwice()
Dim logger As ILogger
Set logger = MockLogger.Create("TestLogger", TraceLevel)
LogManager.Register logger
LogManager.Register logger
End Sub
以上测试通过:
2014-10-04 16:42:55 TestCannotRegisterLoggerTwice: [PASS]
如果我删除ExpectedError“属性”,它会失败:
2014-10-04 16:43:49 TestCannotRegisterLoggerTwice: [INCONCLUSIVE] - Test raised an error: Automation error
到目前为止,一切都很好。嗯,差不多。
测试中的错误可以正常工作!
现在如果我让测试抛出一个除以零,像这样:
'@ExpectedError()
Public Sub TestCannotRegisterLoggerTwice()
Dim logger As ILogger
Set logger = MockLogger.Create("TestLogger", TraceLevel)
Dim boom As Integer
boom = 1 / 0
LogManager.Register logger
LogManager.Register logger
End Sub
测试还没有定论,不过这次正确拾取错误:
2014-10-04 16:45:12 TestCannotRegisterLoggerTwice: [INCONCLUSIVE] - Test raised an error: Division by zero
我不明白的部分是,在这两种情况下,在同一个 VBAProject 中都会引发错误 - 前者在名为 LogManager(SUT)的类中,后者在一个名为LogManagerTests的类。
这是引发我正在测试的预期错误的部分:
Public Sub Register(ByVal logger As ILogger)
If Not this.Loggers.Exists(logger.Name) Then
this.Loggers.Add logger.Name, logger
Else
Err.Raise LogManagerError.DuplicateLoggerError, "LogManager.Register", "There is already a logger registered with name '" & logger.Name & "'."
End If
End Sub
我想要什么
我希望能够用'@ExpectedError(-2147220406)(LogManagerError.DuplicateLoggerError 的Long 表示)来装饰我的测试方法,并能够在TestEngine.ReflectTestMethods 方法中清理这部分:
For Each prospect In classMethods
If CanAddTestMethod(prospect, result) Then
Set tMethod = New TestMethod
Set tMethod.OwnerInstance = classInstance
tMethod.MethodName = prospect.name
If prospect.HasAttribute(ExpectedErrorAttribute) Then
If prospect.AttributeParameters(ExpectedErrorAttribute).Count <> 0 Then
Err.Raise vbObjectError + 1055, "TestEngine.ReflectTestMethods", "ExpectedErrorAttribute for test method '" & prospect.name & "' should not have parameters."
End If
'force an "Automation Error" to be expected,
'because VBA "eats" the expected error thrown in the SUT:
tMethod.ExpectedError = 440 ' prospect.AttributeParameters(ExpectedErrorAttribute).First
End If
result.Add tMethod.MethodName, tMethod
End If
Next
是这样吗?我只能期望 SUT 抛出 自动化错误?
我尝试过的东西
由于在实际测试方法中抛出错误时正确报错,所以我尝试了这个:
'@ExpectedError()
Public Sub TestCannotRegisterLoggerTwice()
On Error GoTo CleanFail
Dim logger As ILogger
Set logger = MockLogger.Create("TestLogger", TraceLevel)
LogManager.Register logger
LogManager.Register logger
Exit Sub
CleanFail:
Dim errNumber As Long
errNumber = Err.Number
Dim errSource As String
errSource = Err.Source
Dim errDescription As String
errDescription = Err.Description
Err.Raise errNumber, errSource, errDescription
End Sub
但即使errDescription 包含正确/预期的错误消息,测试库仍会收到编号为 440 的 自动化错误。
为什么我的测试库正确地选择了除以零,而不是自定义错误?
编辑:经过进一步的实验,我注意到我可以成功地“预期”任何内置错误,所以这是可行的:
'@ExpectedError(5)
Public Sub TestCannotRegisterLoggerTwice()
Dim logger As ILogger
Set logger = MockLogger.Create("TestLogger", TraceLevel)
LogManager.Register logger
LogManager.Register logger
End Sub
...前提是更改我的 TestEngine 代码以接受 @ExpectedError 属性的参数,并且我在 SUT 中引发错误 #5 /“无效的过程调用或参数”,而不是自定义错误;我也无法提供自定义错误消息。这并不理想,因为它会强制 SUT 只抛出内置错误,而我的测试库不能假设是这种情况。
VBA 中的自定义错误代码有什么特别之处?
【问题讨论】:
标签: vba unit-testing error-handling