基于 Java 的 GUI 的 A11Y 和 I18N 测试






2.93/5 (6投票s)
在本文中,我将讨论 Java GUI 的 A11Y 和 I18N 测试。
引言
软件测试有许多不同的方法。可以使用基于模型检查或 Hoare 验证方法的特殊验证工具。也可以使用基本上生成单元测试或基于规范脚本执行简单测试的软件等。
仍然有一种被广泛使用的方法——根据软件规范开发测试套件。
我不想争论最后一种方法的适用性,因为许多公司仍然选择这种方式来测试他们的软件,而且目前仍有大量开发人员在编写测试!
这就是为什么我决定写这篇论文并分享我在这个领域的经验。这里的主要主题将是 Java GUI 的 A11Y 和 I18N 测试。我不会提供任何源代码示例,因为这个主题相当简单。
请注意,在本文中,我假设读者了解以下内容:
- 软件测试
- GUI 测试
- A11Y(无障碍性)
- I18N
- 单元测试
信息
任何了解 Java GUI 测试的人都知道在这一过程中通常使用的以下工具和库:
- XTest
- JUnit
- Jemmy
A11Y 和 I18N 测试的唯一问题是它与单元测试的兼容性很差,并且运行测试的主要工具 XTest 只支持基于 JUnit 的测试。因此,在单元测试的基础上实现多步 GUI 测试是一场灾难。我不会在这里讨论你在此过程中可能遇到的所有麻烦,但下面会提到它们。
Java GUI 测试的问题
首先,让我简要介绍一下 A11Y、I18N 和单元测试是什么:
- A11Y 测试是无障碍性测试,即验证在不使用鼠标的情况下访问每个 GUI 组件的能力。
- I18N 测试是国际化测试,即测试应用程序标签和消息国际化的正确性。
- 单元测试是一种测试系统原子功能的方法。它广泛应用于极限编程(Extreme Programming)以及许多其他情况。例如,当你想要通过测试每个类的方法来测试一个类时。
现在可能很清楚,A11Y 和 I18N GUI 测试与单元测试不兼容。主要原因是任何 GUI 测试通常分为以下几个步骤:
- 执行应用程序启动。设置所需的应用程序选项,打开测试所需的窗口。
- 执行测试用例。
- 启动测试用例 - 对所有测试用例通用。
- 启动测试用例 – 打开一些特殊窗口或设置特定于测试用例的选项。
- 执行测试序列。
- 拆卸测试用例 – 关闭特定窗口并取消设置特定于测试用例的选项。
- 拆卸测试用例 – 对所有测试用例通用。
- 关闭应用程序。
另一方面,单元测试(更准确地说,JUnit 和因此的 Jemmy)假定有一组通用的设置可用于一组测试用例,然后所有这些测试用例都一一执行,并带有通用的关闭。
为了使事情更清楚,请注意,在 GUI 测试的每个步骤中都可能发生故障。这可能会干扰后续步骤的执行,从而极大地影响测试结果。
这是对 GUI 测试开发人员可能面临的问题的简要介绍。在下一节中,我将描述我和我的同事 Alexey V. Ivashchenko 为高效的 A11Y 和 I18N Java GUI 测试所开发的方法。
上述问题的解决方案
解决方案很简单。你需要扩展 JUnit(Jemmy),以便能够创建通用的 StartUp
和 TearDown
方法。开发人员还应该能够添加自定义的 StartUp
和 TearDown
方法。
如果你使用 Jemmy(它不稳定,而且现在可能仍然不稳定),你还必须严格通过 API 函数执行所有 StartUp
和 TearDown
操作,即不要使用鼠标或键盘事件模拟。这将使你能够避免在 StartUp
和 TearDown
操作期间的测试崩溃。
对于 A11Y 测试,还有一个重要的注意事项。任何测试都应该尽可能原子化,例如,向前焦点循环 (Tab) 应该在一个测试用例中测试,向后焦点循环 (Shift-Tab) 在另一个测试用例中测试。此外,每个按钮的按下以及每个组件的可访问性都应该在单独的原子测试用例中进行检查。这将增加测试运行时间,但会大大减少测试套件所需的维护量,并提高其稳定性。就维护而言,我指的是在发现任何 A11Y 错误时需要修改测试用例。
这三个简单的规则将帮助你提高测试套件的稳定性和可维护性。
在接下来的章节中,我将介绍如何扩展 Jemmy 以快速实现 A11Y 和 I18N 测试。
Java GUI 的 I18N 和 A11Y 测试方法
这里描述的方法非常简单但仍然非常有效。我称之为“Checkers”方法。
这里的基本思想是,有一组有限的原子检查(以后称为 AtomicChecker
),它们在 A11Y 和 I18N 测试中执行。例如,在 A11Y 测试中,通常需要检查焦点是否在某个组件上,或者在按下某些键组合后是否会打开一个窗口。对于 I18N 测试,这甚至更明显。这里的主要检查是检查放置在某个组件上的文本标签的值(这包括组合框和窗口标题)。
所以,你所要做的就是创建一个简单的 AtomicCheck
接口,其中几乎只有一个 check
方法,它允许执行组件的原子检查(这里我指的是 Java 组件,例如按钮),然后你所要做的就是创建一个实现它的类集。例如,让我们考虑一下窗体上的一个按钮。
对于 A11Y 测试,可能需要检查在按下 (Tab) 后,该按钮将获得焦点。因此,你用 ButtonA11YAtomicCheck
类实现上面提到的 AtomicCheck
接口,如下所示。这个类应该有一个构造函数,它接收要按下的键组合以及容器(我们的窗体)中按钮的 ID。来自 AtomicCheck
接口的 check
方法首先模拟按下这个键组合,然后查找在获得的 Java 容器(我们的窗体)中具有给定 ID 的按钮,然后检查该按钮是否具有焦点。
对于 I18N 测试,一切都将非常相似,除了构造函数应该接收预期的标签值而不是键组合,并且在 check
方法中,应该将相应的按钮标签与构造函数中提供的标签进行比较。
现在,如果你发挥你的想象力,你就会明白,这个想法与 Java 的多态性相结合,可以为你提供一个相对较小但灵活可扩展的类集(以后称为库),它将允许你执行 A11Y 和 I18N 测试的标准检查。
要执行测试用例,你只需创建一个 AtomicChecker
实现类的实例来执行原子测试。你还可以创建一组不同的实例,它们将逐个激活,并在一个测试用例的范围内执行复杂的测试序列(例如焦点循环检查)。
当然,这只是一个总体思路,一个“精明的读者”明白,还有很多细节和细微之处没有在这篇文章中涉及,但所有这些都可以简单而自然地在提出的范例范围内解决。
所描述方法的主要优点是,如果你想创建一组测试用例,你只需要关心 StartUp
和 TearDown
方法的实现。测试序列本身将只包括实例化具有适当参数的 AtomicChecker
组件,并在循环中启动它们,这个循环当然也应该被统一并提升到 Checkers
库的级别,作为某种性能管理器。
另外请注意,基于 Jemmy 提供的 API 来实现 Checkers
库会非常容易。
结论
在本文中,我简要介绍了软件测试的不同方法,并主要关注 Java GUI 的 A11Y 和 I18N 测试。我展示了任何开发人员在创建测试过程中可能面临的几个问题以及避免这些问题的方法。
本文的主要目的是介绍 Checkers
的新方法,该方法将允许任何人加快 A11Y 和 I18N 测试用例的开发,并提高测试套件的稳定性和可维护性。
参考文献
致谢
我要感谢 Alexey V. Ivashchenko,他参与了 Checkers
方法的开发。