如何对带有第三方dll的.EXE进行单元测试?

6
我仍在学习TDD的黑暗艺术,最近我一直在尝试学习如何在VB6中进行TDD,我基本上将列表缩小到了免费的simplyvbunit和最昂贵的vbunit3。
我的应用程序是一个带有大量第三方dll的richtext编辑器,我在Google上四处搜寻如何对这个exe文件进行单元测试。
所以我的问题是如何对一个exe文件进行单元测试?特别是在VB6的情况下,如果你有任何好的示例与vbunit3或simplyvbunit,你就是一个救命稻草,因为我现在深陷材料中,还不能写出一个单元测试:(
编辑
实际上,应用程序由许多窗体、模块和类模块组成,当我编译它时,它当然会变成一个漂亮的.EXE文件。而且为了使事情更加复杂,有相当数量的全局变量飞来飞去。
但我的主要意图是对代码中所有或大部分易错的部分进行单元测试。我希望确保我可以将测试和代码分开。因此,我认为最好的方法是通过添加引用等方式直接测试exe。

有更好的方法吗?

6个回答

6
单元测试和集成测试之间有区别。你不会对可执行文件进行单元测试。你会对小型、自包含的计算单元进行单元测试,例如方法或过程,这取决于你所使用的语言。集成测试将测试更大的组件,例如API、第三方组件,甚至是可执行文件,以确保它们在给定一组输入(好或坏)时按预期工作。虽然你可以使用单元测试工具对API或插件组件进行一些集成测试,但我认为你不会找到许多适用于测试可执行文件的单元测试工具。还有其他类型的测试工具,可以更好地完成这项工作。对于许多情况而言,编写提供不同类型输入并检查其输出的脚本可能已足够。
如果你想了解更多关于TDD和单元测试的知识,你应该将其应用于VB6中的函数或过程,尽管我建议使用VB.NET(或C#)并进行面向对象开发。通常,这些工具是面向OO风格的编程。

@tvan,但是我所有的函数都编译在exe文件中,那么我该如何测试这些在exe文件中的函数呢?谢谢。 - melaos
1
编译前先进行测试。当我编写程序时,我会创建一个包含所有功能的类库项目。我还会创建另一个包含单元测试的项目。使用单元测试工具中的测试运行器来运行单元测试项目中的类,并对类库中的类进行测试,而不是对可执行文件进行测试。 - tvanfosson
-1 是因为他没有回答关于测试驱动开发的问题,这涉及到集成测试和单元测试的混合。不要太教条主义。 - RS Conley
@RS -- 给定标题,对于什么是单元测试似乎存在一些困惑。我选择尝试澄清而不是增加这种疑惑。当然,在使用TDD的项目中,除了单元测试外还有很多其他类型的测试,比如验收测试、性能测试等。只需要先编写测试,驱动开发即可。 - tvanfosson
@tvanfosson 感谢您的回答。我在程序员堆栈交换上提出了一个相关问题这里这里。我想知道您是否能够指出测试第三方对象代码(没有可用源代码,也没有检查数据即测试工具)的任何问题。 - ha9u63a7
显示剩余3条评论

4
在VB中,ActiveX控件是节省时间的好工具,但它们是有效测试驱动开发的大敌。
为了有效地测试整个VB6应用程序,理想情况下需要设计一个EXE作为ActiveX DLL的薄壳,DLL执行所有工作。表单实现接口并向DLL注册自己。因此,如果您有订单输入表单,它将实现IOrderEntryForm接口,并且其事件将在MyAppUI对话框中的OrderEntry类上调用方法。
强调一下,在Visual Basic 6中,FORMS可以实现接口。然后,该表单在LOAD事件中向UI类注册自己。表单的事件(如MyButton_Click)调用UI类的方法。 UI类使用表单接口的方法来更改显示内容。这是额外的工作,但可以节省很多测试时间。还可以进行维护,只要实施的接口保持不变,就可以更改表单外观。
这也意味着,在拥有MYEXE->MyActiveXDLL之前,您需要将其转换为MYEXE->MyUIDLL->MyActiveXDLL。
对于测试环境,您可以创建一个ActiveX DLL,通过创建实现各种表单接口的类来模拟UI。 UI DLL不知道区别,您完全控制发送什么输入以及读取什么。
请注意,这种设计模式在此处进行了讨论。我将其用作开发和维护我公司的金属切割机CAD / CAM应用程序的基础。
第三方ActiveX控件是此方案的大敌。这是因为执行重要工作的代码位于控件本身内部。 ActiveX控件越复杂,问题就越严重。在我的公司中,趋势是减少我们对第三方控件的依赖,转而使用内部应用程序。
然而,像任何算法和设计模式一样,这涉及判断。您的软件涉及富文本控件的问题有多少个。如果不多,则可以使用测试脚本(手动或自动发送按键到应用程序)并为其余部分使用单元测试框架。
使用单元测试整个应用程序的关键元素是尽可能将其所有内容放入接口后面。现在只需做您能做的事情,并记下您想要更改的区域,以备将来开发之用。如果您没有100%的覆盖率,甚至在未来一年内也不要绝望。

听起来很有趣!希望我的新手VB6技能足以支撑我完成这个项目。谢谢。 - melaos
根据您在答案中的评论,我认为您有很好的机会完成这项任务。只需创建两个测试项目(EXE和ActiveX DLL),以掌握在表单中使用implements关键字的要领。 - RS Conley

1
另一种可用的技术是将您的应用程序制作成ActiveX EXE。然后,您的单元测试应用程序可以将您的应用程序引用为ActiveX DLL。您需要进行相当多的研究才能使其正常工作,因为我最后一次使用VB6已经有一段时间了,我相信有一些技巧可以让它正常工作。

听起来很有趣,但我认为我可能需要查看一些代码示例来了解如何实现。是时候开始谷歌搜索了。谢谢 :) - melaos

0
关于编程方面的建议,我唯一能给出的有用建议就是阅读Michael Feathers的Working Effectively with Legacy Code。我认为你最大的挑战将是你的工具集,因为我知道VB6单元测试的工具并不如其他语言的强大。
你也可以尝试在TDD Yahoo! List上询问,因为我知道至少有几个人在那里使用vbunit3。

也许可以在亚马逊或其他地方链接这本书?可能的话,请提供亚马逊或其他电商平台上这本书的链接。 - MarkJ

0

当然可以对单个EXE进行单元测试。看看有多少应用程序由多个EXE组成。

至于第三方组件,如何使用标准VB6组件进行测试?其他微软组件呢?同样适用于第三方组件。


我同意从理论上讲,.exe或.out文件是“单元”,可以进行测试。我认为人们更想强制实施脚本理论,而不是“单元测试”,因为这有点与敏捷的xUnit测试理念相抵触。 - ha9u63a7

0
为了让事情变得更加复杂,有相当数量的全局变量在飞来飞去。
第一个重构是将全局变量转移到ActiveX DLL中的类中。该类的实例属性需要设置为GLOBAL MULTIUSE。当设置EXE引用ActiveX时,变量仍将是全局的,但是当您拿出EXE以替换它时,测试工具可以访问全局变量。
一旦您进行了测试,就可以进行进一步的重构以减少全局变量的数量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接