23

如何对大型 MFC UI 应用程序进行单元测试?

我们有一些已经开发多年的大型 MFC 应用程序,我们使用一些标准的自动化 QA 工具来运行基本脚本来检查基础、文件打开等。这些由 QA 组在每日构建后运行。

但是我们想介绍一些程序,以便各个开发人员在将代码提交到日常构建之前,可以针对应用程序的对话框、菜单和其他可视元素构建和运行测试。

我听说过诸如仅在调试版本中出现的对话框上的隐藏测试按钮之类的技术,是否有任何标准工具包。

环境是 C++/C/FORTRAN、MSVC 2005、Intel FORTRAN 9.1、Windows XP/Vista x86 & x64。

4

7 回答 7

14

这取决于应用程序的结构。如果逻辑和 GUI 代码是分开的 (MVC),那么测试逻辑很容易。看看 Michael Feathers “Humble Dialog Box” (PDF)。

编辑:如果您考虑一下:如果应用程序的结构不是这样,您应该非常仔细地重构。没有其他技术可以测试逻辑。模拟点击的脚本只是表面上的。

其实很简单:

假设当用户单击按钮时您的控件/窗口/任何更改列表框的内容,并且您希望确保列表框在单击后包含正确的内容。

  1. 重构,以便有一个单独的列表,其中包含要显示的列表框的项目。这些项目存储在列表中,并且不会从您的数据来源中提取。使列表框列表事物的代码只知道新列表。
  2. 然后创建一个包含逻辑代码的新控制器对象。处理按钮点击的方法只调用mycontroller->ButtonWasClicked()。它不知道列表框或其他任何东西。
  3. MyController::ButtonWasClicked() 为预期的逻辑做了需要做的事情,准备项目列表并告诉控件更新。为此,您需要通过为控件创建接口(纯虚拟类)来解耦控制器和控件。控制器只知道该类型的对象,而不知道控件。

就是这样。控制器包含逻辑代码并且仅通过接口知道控制。现在您可以通过模拟控件为 MyController::ButtonWasClicked() 编写常规单元测试。如果您不知道我在说什么,请阅读 Michaels 的文章。两次。在那之后又一次。
(自我提醒:必须学会不要说那么多)

于 2008-09-20T10:40:33.993 回答
14

既然您提到了 MFC,我假设您有一个应用程序很难在自动化测试工具下获得。当您在编写代码时构建测试时,您将观察到单元测试框架的最佳优势。但是,尝试以测试驱动的方式将新功能添加到并非设计为可测试的应用程序中......可能会很辛苦而且很令人沮丧。

现在我要提议的绝对是努力工作.. 但只要有一些纪律和毅力,你很快就会看到好处。

  • 首先,您需要一些管理支持,以便新修复需要更长的时间。确保每个人都明白为什么。
  • 接下来买一本WELC 书。如果您有时间,或者如果您压力很大,请从头到尾阅读它,请扫描索引以查找您的应用程序所表现出的症状。这本书包含了很多很好的建议,这正是你试图让现有代码可测试时所需要的。 替代文字
  • 然后对于每一个新的修复/更改,花一些时间并了解您将要处理的领域。在您选择的 xUnit 变体(免费提供)中编写一些测试来练习当前行为。
  • 确保所有测试都通过。编写一个新的测试来练习需要的行为或错误。
  • 编写代码以使最后一个测试通过。
  • 在测试区域内无情地重构以改进设计。
  • 从这里开始,对您必须对系统进行的每项新更改重复此操作。这条规则没有例外。
  • 现在应许之地:很快,不断增长的经过良好测试的代码孤岛将开始浮出水面。越来越多的代码将属于自动化测试套件,并且更改将变得越来越容易。那是因为底层设计缓慢而可靠地变得更加可测试。

简单的出路是我之前的答案。这是艰难但正确的出路。

于 2008-09-20T13:00:19.883 回答
5

我意识到这是一个过时的问题,但对于我们这些仍在使用 MFC 的人来说,VS2012 中的 Microsoft C++ 单元测试框架运行良好。

一般程序:

  1. 将 MFC 项目编译为静态库
  2. 将新的本机单元测试项目添加到您的解决方案中。
  3. 在测试项目中,添加您的 MFC 项目作为参考。
  4. 在测试项目的配置属性中,为您的头文件添加包含目录。
  5. 在链接器中,输入选项添加您的 MFC.lib;nafxcwd.lib;libcmtd.lib;
  6. 在“忽略特定默认库”下添加 nafxcwd.lib;libcmtd.lib;
  7. 在 General 下添加 MFC 导出的 lib 文件的位置。

https://stackoverflow.com/questions/1146338/error-lnk2005-new-and-delete-already-defined-in-libcmtd-libnew-obj很好地描述了为什么需要 nafxcwd.lib 和 libcmtd.lib .

在遗留项目中检查的另一件重要事情。在常规配置属性中,确保两个项目都使用相同的“字符集”。如果您的 MFC 使用多字节字符集,您也需要 MS 测试来执行此操作。

于 2014-01-29T23:50:28.640 回答
3

虽然不完美,但我为此找到的最好的是 AutoIt http://www.autoitscript.com/autoit3

“AutoIt v3 是一种类似 BASIC 的免费软件脚本语言,旨在自动化 Windows GUI 和一般脚本。它结合了模拟击键、鼠标移动和窗口/控件操作,以一种不可能或可靠的方式自动化任务与其他“

当您可以访问被驱动的应用程序的源代码时,这很有效,因为您可以使用要驱动的控件的资源 ID 号。通过这种方式,您不必担心模拟鼠标单击特定像素。不幸的是,在遗留应用程序中,您可能会发现资源 ID 不是唯一的,这可能会导致问题。然而。将 ID 更改为唯一并重新构建非常简单。

另一个问题是你会遇到时间问题。对于这些,我没有经过验证的真正解决方案。我使用的是反复试验,但这显然是不可扩展的。问题是 AutoIT 脚本必须等待测试应用程序响应命令,然后脚本才能发出下一个命令或检查正确的响应。有时很难找到一个方便的事件来等待和观察。

我的感觉是,在开发一个新的应用程序时,我会坚持以一致的方式发出“READY”的信号。这对人类用户和测试脚本都有帮助!这对于遗留应用程序可能是一个挑战,但也许您可以在有问题的地方引入它,并随着维护的继续慢慢将其传播到整个应用程序。

于 2008-09-20T15:09:49.307 回答
2

虽然它不能处理 UI 端,但我使用 Boost Test 库对 MFC 代码进行单元测试。有一篇关于入门的代码项目文章:

使用 Boost 设计稳健的对象

于 2008-09-20T17:19:03.617 回答
1

好吧,我们在工作场所拥有这些巨大的 MFC 应用程序之一。维持或扩展它是一个巨大的痛苦......它现在是一个巨大的泥球,但它在moolah中耙。无论如何

  • 我们使用Rational Robot进行冒烟测试等。
  • 另一种取得一些成功的方法是创建一个小的产品特定语言和脚本测试,使用 VBScript 和一些 Control 处理间谍魔法。将常用操作转化为命令。例如,OpenDatabase 将是一个命令,该命令反过来将注入所需的脚本块以单击主菜单 > 文件 > “打开...”。然后,您可以创建一系列此类命令的 excel 工作表。这些命令也可以带参数。像 FIT 测试之类的东西.. 但更多的工作。一旦您确定了大多数常用命令并准备好脚本。它是挑选和组装脚本(由 CommandIDs 标记)来编写新测试。测试运行程序解析这些 Excel 表格,将所有小脚本块组合成一个测试脚本并运行它。

    1. 打开数据库“C:\tests\MyDB”
    2. OpenDialog“添加模型”
    3. AddModel "M0001", "MyModel", 2.5, 100
    4. 按确定
    5. 保存数据库

高温高压

于 2008-09-20T10:10:57.840 回答
0

实际上,我们一直在使用 Rational Team Test,然后是 Robot,但在最近与 Rational 的讨论中,我们发现他们没有计划支持更多专注于 .NET 的 Native x64 应用程序,因此我们决定切换自动化 QA 工具。这很好,但许可成本不允许我们为所有开发人员启用它。

我们所有的应用程序都支持用于编写脚本的 COM API,我们通过 VB 对其进行回归测试,但这会测试 API 而不是应用程序本身。

理想情况下,我会对人们如何在开发人员级别将 cppunit 和类似的单元测试框架集成到应用程序中感兴趣。

于 2008-09-20T12:24:12.857 回答