单元测试MFC UI应用程序?

时间:2020-03-06 14:28:48  来源:igfitidea点击:

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

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

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

我听说过这样的技术,例如仅在调试版本中出现的对话框上的隐藏测试按钮,是否有用于此目的的标准工具包。

环境是C ++ / C / FORTRAN,MSVC 2005,Intel FORTRAN 9.1,Windows XP / Vista x86和x64.

解决方案

好吧,我们在工作场所中拥有这些庞大的MFC应用程序之一。它是维持或者延长它的巨大痛苦...现在它是一个巨大的泥球,但它在草丛中耙开了。

  • 我们使用Rational Robot进行烟雾测试等。
  • OpenDialog"添加模型"
  • AddModel" M0001"," MyModel",2.5、100
  • 按确定
  • 保存数据库

高温超导

这取决于应用程序的结构。如果逻辑和GUI代码是分开的(MVC),则测试逻辑很容易。看看Michael Feathers的"谦虚对话框"(PDF)。

编辑:如果我们考虑过:如果应用程序的结构不是这样,则应该非常仔细地重构。没有其他测试逻辑的技术。模拟点击的脚本只是在抓挠表面。

实际上很简单:

假定控件/窗口/在用户单击按钮时要更改列表框的内容,并且我们想确保单击后列表框包含正确的内容。

  • 进行重构,以便有一个单独的列表,其中包含要显示的列表框的项目。这些项目存储在列表中,并且不会从数据来源中提取出来。使列表框列出所有内容的代码仅知道新列表。
  • 然后,我们将创建一个新的控制器对象,其中将包含逻辑代码。处理按钮单击的方法仅调用mycontroller-> ButtonWasClicked()。它不知道列表框或者其他内容。
  • MyController :: ButtonWasClicked()完成所需逻辑的准备工作,准备项目列表并告诉控件进行更新。为此,我们需要通过为控件创建接口(纯虚拟类)来分离控制器和控件。控制器仅知道该类型的对象,而不知道控件。

而已。控制器包含逻辑代码,并且仅通过接口知道控制。现在,我们可以通过模拟控件编写MyController :: ButtonWasClicked()的常规单元测试。如果我们不知道我在说什么,请阅读Michaels的文章。两次。再之后。
(自我注意:必须学会不要胡说太多)

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

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

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

自从我们提到MFC以来,我假设我们拥有一个很难在自动测试工具下获得的应用程序。编写代码时,在构建测试时,我们将观察到单元测试框架的最大好处。但是,尝试以测试驱动的方式向并非设计为可测试的应用程序中添加新功能可能会很困难。好沮丧

现在,我要提出的无疑是艰苦的工作..但是只要有一定的纪律和毅力,我们很快就会看到好处。

  • 首先,我们需要一些管理支持,以使新修复花费更长的时间。确保每个人都明白原因。
  • 接下来购买一本WELC书籍。如果有时间,请仔细阅读封面内容,或者如果用力按压,请扫描索引以查找应用所表现出的症状。本书包含很多不错的建议,而这正是我们尝试使现有代码可测试时所需要的。替代文字http://ecx.images-amazon.com/images/I/51RCXGPXQ8L.SL160_AA115.jpg
  • 然后,对于每个新的修复程序/更改,请花一些时间并了解我们将要进行的工作领域。在我们选择的xUnit变体(免费提供)中编写一些测试以行使当前行为。
  • 确保所有测试均通过。编写一个新的测试,以测试所需的行为或者错误。
  • 编写代码以完成最后的测试。
  • 在测试区域内无情地进行重构以改善设计。
  • 从此开始,对我们必须对系统进行的每个新更改重复此操作。此规则无例外。
  • 现在是有希望的土地:越来越多的经过良好测试的代码的孤岛很快就会开始浮出水面。越来越多的代码将属于自动化测试套件,并且更改将变得越来越容易进行。那是因为底层设计可以缓慢而可靠地变得更具可测试性。

轻松的出路是我以前的答案。这是困难而正确的出路。

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

" AutoIt v3是一种类似于BASIC的免费软件,旨在自动执行Windows GUI和常规脚本。它结合了模拟的击键,鼠标移动和窗口/控件操作,从而以其他方式无法实现或者不可靠的方式自动执行任务语言(例如VBScript和SendKeys)。AutoIt也非常小巧,功能齐全,可以直接在所有版本的Windows上运行,而无需烦人的"运行时"!"

当我们可以访问要驱动的应用程序的源代码时,此方法效果很好,因为我们可以使用要驱动的控件的资源ID号。这样,我们不必担心特定像素上的模拟鼠标单击。不幸的是,在旧版应用程序中,我们很可能会发现资源ID不是唯一的,这可能会引起问题。然而。将ID更改为唯一并重新构建非常简单。

另一个问题是我们将遇到计时问题。对于这些,我还没有一个经过尝试的真实解决方案。我经常使用试错法,但这显然是不可扩展的。问题在于,AutoIT脚本必须等待测试应用程序对命令作出响应,然后脚本才能发出下一个命令或者检查是否有正确的响应。有时候,找到一个方便的事件来等待观察并不容易。

我的感觉是,在开发新应用程序时,我将坚持以一致的方式表示"就绪"。这对人类用户以及测试脚本都将有所帮助!对于旧版应用程序来说,这可能是一个挑战,但是也许我们可以在有问题的地方引入它,并在维护继续时将其缓慢地传播到整个应用程序中。

尽管它不能处理UI方面,但我使用Boost Test库对MFC代码进行单元测试。关于入门的代码项目文章:

使用Boost设计坚固的对象