我的代码中的计算经过了充分测试,但由于有大量GUI代码,我的整体代码覆盖率比我想要的低。是否有关于单元测试GUI代码的指导方针?这甚至有意义吗?
例如,在我的应用程序中有图表。我无法找到如何自动化测试图表的方法。据我所知,需要人眼来检查图表是否正确。
(我正在使用Java Swing)
我的代码中的计算经过了充分测试,但由于有大量GUI代码,我的整体代码覆盖率比我想要的低。是否有关于单元测试GUI代码的指导方针?这甚至有意义吗?
例如,在我的应用程序中有图表。我无法找到如何自动化测试图表的方法。据我所知,需要人眼来检查图表是否正确。
(我正在使用Java Swing)
像MVP和MVC这样的设计通常试图尽可能地将逻辑抽象出实际的GUI。关于这个问题,Michael Feathers 的文章 "谦卑的对话框" 是非常流行的一篇文章。就我个人而言,尝试将逻辑移出UI会有好有坏,有时效果很好,而另外一些时候则得不偿失。但是这也超出了我的专业领域。
当然,答案是使用MVC并尽可能将逻辑移出GUI。
话虽如此,我曾经从一位同事那里听说,当SGI将OpenGL移植到新硬件时,他们有一堆单元测试会将一组基本图形绘制到屏幕上,然后计算帧缓冲区的MD5值。通过与已知的好哈希值进行比较,可以快速确定API是否按像素精确。
(2^32) - 1
和(2^32) - 2
之间的差异一样。也就是说,至少根据我理解你的评论,你必须看到雪崩效应才能检测到不同的值。这不应该是这种情况。任何旧的哈希算法(包括非加密选项)都应该适用于这种用例,因为重复的机会和抵抗预像攻击的能力应该是无关紧要的。话虽如此,我会使用MD5。 - Spencer D你可以尝试使用UISpec4J, 它是一个开源的功能和/或单元测试库,适用于基于Swing的Java应用程序...
测试是一种艺术形式。我同意逻辑应该尽可能地从GUI中移除。我们可以将重点放在单元测试上。像任何其他测试一样,测试的目的是为了降低风险。你并不总是需要测试所有内容,但很多时候最好将不同的测试分开进行。
另一个问题是,你真正想要在UI层面测试什么。UI测试是最昂贵的测试,因为通常需要更长时间来创建和维护,并且它也是最脆弱的。如果你在尝试绘制线之前测试逻辑以确保坐标正确,你具体在测试什么?如果你想要测试一个带有红线的图表,可以给它设置预定坐标并测试某些像素是否为红色或非红色吗?如上所述,位图比较、Selenium都可以使用,但我的主要重点是不要过度测试GUI,而是测试将有助于创建UI的逻辑,然后专注于UI的哪个部分会出现故障或可疑,并在那里进行少量的测试。
有一个名为Selenium RC的工具,它可以自动化测试基于Web的用户界面。它会记录操作并重放它们。您仍然需要手动执行与您的UI的交互,因此它不会帮助覆盖范围,但它可用于自动构建。
Scenario: Dialog manipulation
Given the frame "SwingSet" is visible
When I click the menu "File/About"
Then I should see the dialog "About Swing!"
When I click the button "OK"
Then I should not see the dialog "About Swing!"
请查看这个Swinger视频演示以查看它的实际效果。
以下是一些提示:
尽量从GUI中删除大部分代码(使用控制器和模型对象),这样您就可以在没有GUI的情况下测试它们。
对于图形,您应该测试提供给生成图形代码的值。
手动测试。 在编码过程中,您始终保持GUI运行,并确保它与代码同步。您会在工作时手动测试和反复测试您所工作的部分,不断在代码和运行应用程序之间切换。每当您完成一些重要的工作时,您会对整个屏幕或应用程序区域进行全面测试,以确保没有回归。
单元测试。 您为函数或小的GUI行为单元编写测试。例如,您的图表可能需要根据“基础”颜色计算不同的颜色阴影。您可以将此计算提取到一个函数中并为其编写单元测试。您可以在GUI中搜索这样的逻辑(特别是可重用逻辑),并将其提取到离散函数中,这样更容易进行单元测试。甚至可以通过这种方式提取和测试复杂的行为–例如,向导中的一系列步骤可以提取到一个函数中,单元测试可以验证在给定输入的情况下,返回正确的步骤。
组件浏览器。 您创建一个“浏览器”屏幕,其唯一作用是展示组成您GUI的每个可重用组件。此屏幕可快速轻松地验证每个组件是否具有正确的外观和感觉。组件浏览器比手动浏览整个应用程序更有效,因为A)您只需验证每个组件一次,B)您不必深入应用程序中查看组件,只需立即查看并验证它。
自动化测试。 您编写一个与屏幕或组件交互的测试,模拟鼠标单击,数据输入等,断言应用程序在进行这些操作时是否正常运行。这可以作为额外的备份测试,捕获其他测试可能会错过的潜在错误。我倾向于将自动化测试保留给最容易出错和/或非常关键的GUI部分。其中我希望尽早知道是否出现问题的部分。这可能包括高度复杂的交互式组件容易出错或重要的主要屏幕。
差异/快照测试。 您编写一个简单的测试,将输出捕获为屏幕截图或HTML代码,并将其与先前的输出进行比较。这样,每当输出发生变化时,您都会收到提醒。如果您的GUI的视觉方面很复杂和/或易于更改,则差异测试可能很有用,在这种情况下,您希望快速获得有关给定更改对整个GUI的影响的视觉反馈。
您可以使用JFCUnit来测试GUI,但图形可能更具挑战性。我曾经几次拍摄了我的GUI的快照,并自动将其与先前版本进行比较。虽然这并不提供实际测试,但如果自动构建未能产生预期输出,它会向您发出警报。