我正在用RubberDuck开发测试,并希望测试程序中的MsgBox输出。问题是,程序在输出MsgBox之后就结束了--实际上有一个"End“语句。
当运行RubberDuck测试并使用Fakes.MsgBox.Returns时,有一个非决定性的黄色结果,即消息“运行测试时意外的COM异常”
我试着在测试的末尾放置一个"Assert.Fail“;但是,程序的结尾似乎会抛出一些东西。
RubberDuck中的测试是否有可能检测程序是否结束?
发布于 2018-12-26 00:04:46
tldr;否
Rubber鸭单元测试是在VBA运行时的上下文中执行的,也就是说,VBA单元测试代码是从主机应用程序内部运行的。通过API将测试结果报告给Rubber鸭子。如果您查看插入测试模块时生成的VBA代码,它将给出测试运行方式的基本概念。例如,我们的集成测试套件中的这个单元测试:
'HERE BE DRAGONS. Save your work in ALL open windows.
'@TestModule
'@Folder("Tests")
Private Assert As New Rubberduck.AssertClass
Private Fakes As New Rubberduck.FakesProvider
'@TestMethod
Public Sub InputBoxFakeWorks()
On Error GoTo TestFail
Dim userInput As String
With Fakes.InputBox
.Returns vbNullString, 1
.ReturnsWhen "Prompt", "Second", "User entry 2", 2
userInput = InputBox("First")
Assert.IsTrue userInput = vbNullString
userInput = InputBox("Second")
Assert.IsTrue userInput = "User entry 2"
End With
TestExit:
Exit Sub
TestFail:
Assert.Fail "Test raised an error: #" & Err.Number & " - " & Err.Description
End Sub分解:
这将创建一个托管类,用于“侦听”正在测试的代码中的断言,并评估通过或失败测试的条件。
Private Assert As New Rubberduck.AssertClass FakesProvider是一个实用程序对象,用于将VB运行时中的钩子设置为“忽略”或“欺骗”VB运行时内部对InputBox函数的调用。
由于Fakes对象被声明为As New,所以With块为测试实例化了一个FakesProvider。InputBox方法Fakes,它在vbe7.dll中为rtcInputBox函数设置一个钩子,它将所有流量从VBA重定向到该函数到Rubber鸭实现。它现在正在计数调用、跟踪传递的参数、提供返回值等。
With Fakes.InputBox返回和ReturnsWhen调用使用VBA对象将假调用的测试设置与InputBox通信。在本例中,它将InputBox对象配置为返回调用1的vbNullString,在传递调用2的"Second"的Prompt参数时返回“用户条目2”。
.Returns vbNullString, 1
.ReturnsWhen "Prompt", "Second", "User entry 2", 2这就是AssertClass进来的地方。当您从Rubber鸭UI运行单元测试时,它将确定用户代码的COM界面。然后,它通过该接口调用测试方法。然后,Rubber鸭使用AssertClass测试运行时条件。IsTrue方法将Boolean作为参数(带有可选输出消息)。因此,在下面的代码行中,VB计算表达式userInput = vbNullString并将结果作为参数传递给IsTrue。然后,Rubber鸭IsTrue实现根据从VBA传递的参数是否满足调用AssertClass方法的条件来设置单元测试的状态。
Assert.IsTrue userInput = vbNullString就你的问题而言,这意味着什么:
注意,在上面的代码执行方式的细分中,所有内容都是在VBA环境中执行的。Rubber鸭为VBA提供了一个“窗口”,通过AssertClass对象报告结果,并通过FakesProvider对象提供钩子服务(对于“简单”的一些值)。VBA“拥有”这两个对象--它们只是通过Rubber鸭的COM提供者提供的。
当您在VBA中使用End语句时,它强制终止在这一点上的执行。Rubber鸭COM对象不再由客户端主动引用(您的测试过程),并且它没有定义是否会减少COM对象上的引用计数。就像拔掉墙上的插头一样。Rubber鸭在这一点上唯一能确定的是COM客户端已经断开连接。在您的例子中,它表现为一个在Rubber鸭子中捕获的COM异常。由于Rubber鸭无法知道它所提供的对象为什么失去了通信,所以它将测试结果报告为“不确定”--它没有完成测试。
尽管如此,解决方案是重构代码以避免使用End。永远不会。引用上面链接的文档End..。
立即终止执行。它本身从来不需要,但可以放置在一个过程中的任何地方,以结束代码执行、关闭使用Open语句打开的文件和清除变量。
这一点远远不够优雅,而且如果您有对其他COM对象(除了Rubber鸭子)的引用,就无法保证它们将可靠地终止。
完全公开后,我为Rubber鸭子项目贡献了部分代码,并编写了上述代码。如果您想更好地了解单元测试功能(并且可以读取c#),COM提供者可以在此链接上找到的实现。
https://stackoverflow.com/questions/53926116
复制相似问题